diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2010-07-20 18:21:01 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-07-28 10:06:00 -0400 |
commit | 24f089e2f2c800f88039e9d536d558ec6e349fad (patch) | |
tree | 59cf263f112e176015a3a37c3928cc3d2a4dfcb5 | |
parent | 251748a99e631a2c46edcf9e519cfc60fae8153d (diff) |
[SCSI] libfc: add fc_fill_reply_hdr() and fc_fill_hdr()
Add functions to fill in an FC header given a request header.
These reduces code lines in fc_lport and fc_rport and works
without an exchange/sequence assigned.
fc_fill_reply_hdr() fills a header for a final reply frame.
fc_fill_hdr() which is similar but allows specifying the
f_ctl parameter.
Add defines for F_CTL values FC_FCTL_REQ and FC_FCTL_RESP.
These can be used for most request and response sequences.
v2 of patch adds a line to copy the frame encapsulation
info from the received frame.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
-rw-r--r-- | drivers/scsi/libfc/fc_elsct.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 6 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_libfc.c | 78 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 39 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 64 | ||||
-rw-r--r-- | include/scsi/fc_encode.h | 7 | ||||
-rw-r--r-- | include/scsi/libfc.h | 4 |
7 files changed, 121 insertions, 79 deletions
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index e9412b710fab..9b25969e2ad0 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c | |||
@@ -64,7 +64,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, | |||
64 | } | 64 | } |
65 | 65 | ||
66 | fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, | 66 | fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, |
67 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 67 | FC_FCTL_REQ, 0); |
68 | 68 | ||
69 | return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); | 69 | return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); |
70 | } | 70 | } |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 61a12970bd14..eac4d09314eb 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -1108,7 +1108,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp, | |||
1108 | 1108 | ||
1109 | fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id, | 1109 | fc_fill_fc_hdr(fp, FC_RCTL_DD_UNSOL_CMD, rport->port_id, |
1110 | rpriv->local_port->port_id, FC_TYPE_FCP, | 1110 | rpriv->local_port->port_id, FC_TYPE_FCP, |
1111 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 1111 | FC_FCTL_REQ, 0); |
1112 | 1112 | ||
1113 | seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, | 1113 | seq = lport->tt.exch_seq_send(lport, fp, resp, fc_fcp_pkt_destroy, |
1114 | fsp, 0); | 1114 | fsp, 0); |
@@ -1381,7 +1381,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp) | |||
1381 | fr_seq(fp) = fsp->seq_ptr; | 1381 | fr_seq(fp) = fsp->seq_ptr; |
1382 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id, | 1382 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rport->port_id, |
1383 | rpriv->local_port->port_id, FC_TYPE_ELS, | 1383 | rpriv->local_port->port_id, FC_TYPE_ELS, |
1384 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 1384 | FC_FCTL_REQ, 0); |
1385 | if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, | 1385 | if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC, |
1386 | fc_fcp_rec_resp, fsp, | 1386 | fc_fcp_rec_resp, fsp, |
1387 | jiffies_to_msecs(FC_SCSI_REC_TOV))) { | 1387 | jiffies_to_msecs(FC_SCSI_REC_TOV))) { |
@@ -1639,7 +1639,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) | |||
1639 | 1639 | ||
1640 | fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id, | 1640 | fc_fill_fc_hdr(fp, FC_RCTL_ELS4_REQ, rport->port_id, |
1641 | rpriv->local_port->port_id, FC_TYPE_FCP, | 1641 | rpriv->local_port->port_id, FC_TYPE_FCP, |
1642 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | 1642 | FC_FCTL_REQ, 0); |
1643 | 1643 | ||
1644 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, | 1644 | seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL, |
1645 | fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); | 1645 | fsp, jiffies_to_msecs(FC_SCSI_REC_TOV)); |
diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c index 39f4b6ab04b4..6a48c28e4420 100644 --- a/drivers/scsi/libfc/fc_libfc.c +++ b/drivers/scsi/libfc/fc_libfc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/crc32.h> | 23 | #include <linux/crc32.h> |
24 | 24 | ||
25 | #include <scsi/libfc.h> | 25 | #include <scsi/libfc.h> |
26 | #include <scsi/fc_encode.h> | ||
26 | 27 | ||
27 | #include "fc_libfc.h" | 28 | #include "fc_libfc.h" |
28 | 29 | ||
@@ -132,3 +133,80 @@ u32 fc_copy_buffer_to_sglist(void *buf, size_t len, | |||
132 | } | 133 | } |
133 | return copy_len; | 134 | return copy_len; |
134 | } | 135 | } |
136 | |||
137 | /** | ||
138 | * fc_fill_hdr() - fill FC header fields based on request | ||
139 | * @fp: reply frame containing header to be filled in | ||
140 | * @in_fp: request frame containing header to use in filling in reply | ||
141 | * @r_ctl: R_CTL value for header | ||
142 | * @f_ctl: F_CTL value for header, with 0 pad | ||
143 | * @seq_cnt: sequence count for the header, ignored if frame has a sequence | ||
144 | * @parm_offset: parameter / offset value | ||
145 | */ | ||
146 | void fc_fill_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, | ||
147 | enum fc_rctl r_ctl, u32 f_ctl, u16 seq_cnt, u32 parm_offset) | ||
148 | { | ||
149 | struct fc_frame_header *fh; | ||
150 | struct fc_frame_header *in_fh; | ||
151 | struct fc_seq *sp; | ||
152 | u32 fill; | ||
153 | |||
154 | fh = __fc_frame_header_get(fp); | ||
155 | in_fh = __fc_frame_header_get(in_fp); | ||
156 | |||
157 | if (f_ctl & FC_FC_END_SEQ) { | ||
158 | fill = -fr_len(fp) & 3; | ||
159 | if (fill) { | ||
160 | /* TODO, this may be a problem with fragmented skb */ | ||
161 | memset(skb_put(fp_skb(fp), fill), 0, fill); | ||
162 | f_ctl |= fill; | ||
163 | } | ||
164 | fr_eof(fp) = FC_EOF_T; | ||
165 | } else { | ||
166 | WARN_ON(fr_len(fp) % 4 != 0); /* no pad to non last frame */ | ||
167 | fr_eof(fp) = FC_EOF_N; | ||
168 | } | ||
169 | |||
170 | fh->fh_r_ctl = r_ctl; | ||
171 | memcpy(fh->fh_d_id, in_fh->fh_s_id, sizeof(fh->fh_d_id)); | ||
172 | memcpy(fh->fh_s_id, in_fh->fh_d_id, sizeof(fh->fh_s_id)); | ||
173 | fh->fh_type = in_fh->fh_type; | ||
174 | hton24(fh->fh_f_ctl, f_ctl); | ||
175 | fh->fh_ox_id = in_fh->fh_ox_id; | ||
176 | fh->fh_rx_id = in_fh->fh_rx_id; | ||
177 | fh->fh_cs_ctl = 0; | ||
178 | fh->fh_df_ctl = 0; | ||
179 | fh->fh_parm_offset = htonl(parm_offset); | ||
180 | |||
181 | sp = fr_seq(in_fp); | ||
182 | if (sp) { | ||
183 | fr_seq(fp) = sp; | ||
184 | fh->fh_seq_id = sp->id; | ||
185 | seq_cnt = sp->cnt; | ||
186 | } else { | ||
187 | fh->fh_seq_id = 0; | ||
188 | } | ||
189 | fh->fh_seq_cnt = ntohs(seq_cnt); | ||
190 | fr_sof(fp) = seq_cnt ? FC_SOF_N3 : FC_SOF_I3; | ||
191 | fr_encaps(fp) = fr_encaps(in_fp); | ||
192 | } | ||
193 | EXPORT_SYMBOL(fc_fill_hdr); | ||
194 | |||
195 | /** | ||
196 | * fc_fill_reply_hdr() - fill FC reply header fields based on request | ||
197 | * @fp: reply frame containing header to be filled in | ||
198 | * @in_fp: request frame containing header to use in filling in reply | ||
199 | * @r_ctl: R_CTL value for reply | ||
200 | * @parm_offset: parameter / offset value | ||
201 | */ | ||
202 | void fc_fill_reply_hdr(struct fc_frame *fp, const struct fc_frame *in_fp, | ||
203 | enum fc_rctl r_ctl, u32 parm_offset) | ||
204 | { | ||
205 | struct fc_seq *sp; | ||
206 | |||
207 | sp = fr_seq(in_fp); | ||
208 | if (sp) | ||
209 | fr_seq(fp) = fr_dev(in_fp)->tt.seq_start_next(sp); | ||
210 | fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset); | ||
211 | } | ||
212 | EXPORT_SYMBOL(fc_fill_reply_hdr); | ||
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index be3c2cee829f..e50a6606d4bf 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -405,11 +405,9 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
405 | struct fc_lport *lport) | 405 | struct fc_lport *lport) |
406 | { | 406 | { |
407 | struct fc_frame *fp; | 407 | struct fc_frame *fp; |
408 | struct fc_exch *ep = fc_seq_exch(sp); | ||
409 | unsigned int len; | 408 | unsigned int len; |
410 | void *pp; | 409 | void *pp; |
411 | void *dp; | 410 | void *dp; |
412 | u32 f_ctl; | ||
413 | 411 | ||
414 | FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n", | 412 | FC_LPORT_DBG(lport, "Received ECHO request while in state %s\n", |
415 | fc_lport_state(lport)); | 413 | fc_lport_state(lport)); |
@@ -425,11 +423,8 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
425 | dp = fc_frame_payload_get(fp, len); | 423 | dp = fc_frame_payload_get(fp, len); |
426 | memcpy(dp, pp, len); | 424 | memcpy(dp, pp, len); |
427 | *((__be32 *)dp) = htonl(ELS_LS_ACC << 24); | 425 | *((__be32 *)dp) = htonl(ELS_LS_ACC << 24); |
428 | sp = lport->tt.seq_start_next(sp); | 426 | fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); |
429 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | 427 | lport->tt.frame_send(lport, fp); |
430 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
431 | FC_TYPE_ELS, f_ctl, 0); | ||
432 | lport->tt.seq_send(lport, sp, fp); | ||
433 | } | 428 | } |
434 | fc_frame_free(in_fp); | 429 | fc_frame_free(in_fp); |
435 | } | 430 | } |
@@ -447,7 +442,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
447 | struct fc_lport *lport) | 442 | struct fc_lport *lport) |
448 | { | 443 | { |
449 | struct fc_frame *fp; | 444 | struct fc_frame *fp; |
450 | struct fc_exch *ep = fc_seq_exch(sp); | ||
451 | struct fc_els_rnid *req; | 445 | struct fc_els_rnid *req; |
452 | struct { | 446 | struct { |
453 | struct fc_els_rnid_resp rnid; | 447 | struct fc_els_rnid_resp rnid; |
@@ -457,7 +451,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
457 | struct fc_seq_els_data rjt_data; | 451 | struct fc_seq_els_data rjt_data; |
458 | u8 fmt; | 452 | u8 fmt; |
459 | size_t len; | 453 | size_t len; |
460 | u32 f_ctl; | ||
461 | 454 | ||
462 | FC_LPORT_DBG(lport, "Received RNID request while in state %s\n", | 455 | FC_LPORT_DBG(lport, "Received RNID request while in state %s\n", |
463 | fc_lport_state(lport)); | 456 | fc_lport_state(lport)); |
@@ -490,12 +483,8 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
490 | memcpy(&rp->gen, &lport->rnid_gen, | 483 | memcpy(&rp->gen, &lport->rnid_gen, |
491 | sizeof(rp->gen)); | 484 | sizeof(rp->gen)); |
492 | } | 485 | } |
493 | sp = lport->tt.seq_start_next(sp); | 486 | fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); |
494 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; | 487 | lport->tt.frame_send(lport, fp); |
495 | f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; | ||
496 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
497 | FC_TYPE_ELS, f_ctl, 0); | ||
498 | lport->tt.seq_send(lport, sp, fp); | ||
499 | } | 488 | } |
500 | } | 489 | } |
501 | fc_frame_free(in_fp); | 490 | fc_frame_free(in_fp); |
@@ -800,14 +789,13 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | |||
800 | struct fc_lport *lport) | 789 | struct fc_lport *lport) |
801 | { | 790 | { |
802 | struct fc_frame *fp; | 791 | struct fc_frame *fp; |
792 | struct fc_frame_header *fh; | ||
803 | struct fc_seq *sp; | 793 | struct fc_seq *sp; |
804 | struct fc_exch *ep; | ||
805 | struct fc_els_flogi *flp; | 794 | struct fc_els_flogi *flp; |
806 | struct fc_els_flogi *new_flp; | 795 | struct fc_els_flogi *new_flp; |
807 | u64 remote_wwpn; | 796 | u64 remote_wwpn; |
808 | u32 remote_fid; | 797 | u32 remote_fid; |
809 | u32 local_fid; | 798 | u32 local_fid; |
810 | u32 f_ctl; | ||
811 | 799 | ||
812 | FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", | 800 | FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", |
813 | fc_lport_state(lport)); | 801 | fc_lport_state(lport)); |
@@ -843,7 +831,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | |||
843 | 831 | ||
844 | fp = fc_frame_alloc(lport, sizeof(*flp)); | 832 | fp = fc_frame_alloc(lport, sizeof(*flp)); |
845 | if (fp) { | 833 | if (fp) { |
846 | sp = lport->tt.seq_start_next(fr_seq(rx_fp)); | ||
847 | new_flp = fc_frame_payload_get(fp, sizeof(*flp)); | 834 | new_flp = fc_frame_payload_get(fp, sizeof(*flp)); |
848 | fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI); | 835 | fc_lport_flogi_fill(lport, new_flp, ELS_FLOGI); |
849 | new_flp->fl_cmd = (u8) ELS_LS_ACC; | 836 | new_flp->fl_cmd = (u8) ELS_LS_ACC; |
@@ -852,11 +839,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, | |||
852 | * Send the response. If this fails, the originator should | 839 | * Send the response. If this fails, the originator should |
853 | * repeat the sequence. | 840 | * repeat the sequence. |
854 | */ | 841 | */ |
855 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | 842 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
856 | ep = fc_seq_exch(sp); | 843 | fh = fc_frame_header_get(fp); |
857 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, remote_fid, local_fid, | 844 | hton24(fh->fh_s_id, local_fid); |
858 | FC_TYPE_ELS, f_ctl, 0); | 845 | hton24(fh->fh_d_id, remote_fid); |
859 | lport->tt.seq_send(lport, sp, fp); | 846 | lport->tt.frame_send(lport, fp); |
860 | 847 | ||
861 | } else { | 848 | } else { |
862 | fc_lport_error(lport, fp); | 849 | fc_lport_error(lport, fp); |
@@ -1731,8 +1718,7 @@ static int fc_lport_els_request(struct fc_bsg_job *job, | |||
1731 | hton24(fh->fh_d_id, did); | 1718 | hton24(fh->fh_d_id, did); |
1732 | hton24(fh->fh_s_id, lport->port_id); | 1719 | hton24(fh->fh_s_id, lport->port_id); |
1733 | fh->fh_type = FC_TYPE_ELS; | 1720 | fh->fh_type = FC_TYPE_ELS; |
1734 | hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | | 1721 | hton24(fh->fh_f_ctl, FC_FCTL_REQ); |
1735 | FC_FC_END_SEQ | FC_FC_SEQ_INIT); | ||
1736 | fh->fh_cs_ctl = 0; | 1722 | fh->fh_cs_ctl = 0; |
1737 | fh->fh_df_ctl = 0; | 1723 | fh->fh_df_ctl = 0; |
1738 | fh->fh_parm_offset = 0; | 1724 | fh->fh_parm_offset = 0; |
@@ -1791,8 +1777,7 @@ static int fc_lport_ct_request(struct fc_bsg_job *job, | |||
1791 | hton24(fh->fh_d_id, did); | 1777 | hton24(fh->fh_d_id, did); |
1792 | hton24(fh->fh_s_id, lport->port_id); | 1778 | hton24(fh->fh_s_id, lport->port_id); |
1793 | fh->fh_type = FC_TYPE_CT; | 1779 | fh->fh_type = FC_TYPE_CT; |
1794 | hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ | | 1780 | hton24(fh->fh_f_ctl, FC_FCTL_REQ); |
1795 | FC_FC_END_SEQ | FC_FC_SEQ_INIT); | ||
1796 | fh->fh_cs_ctl = 0; | 1781 | fh->fh_cs_ctl = 0; |
1797 | fh->fh_df_ctl = 0; | 1782 | fh->fh_df_ctl = 0; |
1798 | fh->fh_parm_offset = 0; | 1783 | fh->fh_parm_offset = 0; |
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 123493166824..598795123211 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -746,9 +746,8 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, | |||
746 | struct fc_els_flogi *flp; | 746 | struct fc_els_flogi *flp; |
747 | struct fc_rport_priv *rdata; | 747 | struct fc_rport_priv *rdata; |
748 | struct fc_frame *fp = rx_fp; | 748 | struct fc_frame *fp = rx_fp; |
749 | struct fc_exch *ep; | ||
750 | struct fc_seq_els_data rjt_data; | 749 | struct fc_seq_els_data rjt_data; |
751 | u32 sid, f_ctl; | 750 | u32 sid; |
752 | 751 | ||
753 | rjt_data.fp = NULL; | 752 | rjt_data.fp = NULL; |
754 | sid = fc_frame_sid(fp); | 753 | sid = fc_frame_sid(fp); |
@@ -813,7 +812,6 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, | |||
813 | rjt_data.explan = ELS_EXPL_NONE; | 812 | rjt_data.explan = ELS_EXPL_NONE; |
814 | goto reject; | 813 | goto reject; |
815 | } | 814 | } |
816 | fc_frame_free(rx_fp); | ||
817 | 815 | ||
818 | fp = fc_frame_alloc(lport, sizeof(*flp)); | 816 | fp = fc_frame_alloc(lport, sizeof(*flp)); |
819 | if (!fp) | 817 | if (!fp) |
@@ -824,11 +822,8 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, | |||
824 | flp = fc_frame_payload_get(fp, sizeof(*flp)); | 822 | flp = fc_frame_payload_get(fp, sizeof(*flp)); |
825 | flp->fl_cmd = ELS_LS_ACC; | 823 | flp->fl_cmd = ELS_LS_ACC; |
826 | 824 | ||
827 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; | 825 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
828 | ep = fc_seq_exch(sp); | 826 | lport->tt.frame_send(lport, fp); |
829 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
830 | FC_TYPE_ELS, f_ctl, 0); | ||
831 | lport->tt.seq_send(lport, sp, fp); | ||
832 | 827 | ||
833 | if (rdata->ids.port_name < lport->wwpn) | 828 | if (rdata->ids.port_name < lport->wwpn) |
834 | fc_rport_enter_plogi(rdata); | 829 | fc_rport_enter_plogi(rdata); |
@@ -837,12 +832,13 @@ static void fc_rport_recv_flogi_req(struct fc_lport *lport, | |||
837 | out: | 832 | out: |
838 | mutex_unlock(&rdata->rp_mutex); | 833 | mutex_unlock(&rdata->rp_mutex); |
839 | mutex_unlock(&disc->disc_mutex); | 834 | mutex_unlock(&disc->disc_mutex); |
835 | fc_frame_free(rx_fp); | ||
840 | return; | 836 | return; |
841 | 837 | ||
842 | reject: | 838 | reject: |
843 | mutex_unlock(&disc->disc_mutex); | 839 | mutex_unlock(&disc->disc_mutex); |
844 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | 840 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); |
845 | fc_frame_free(fp); | 841 | fc_frame_free(rx_fp); |
846 | } | 842 | } |
847 | 843 | ||
848 | /** | 844 | /** |
@@ -1310,10 +1306,8 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, | |||
1310 | { | 1306 | { |
1311 | struct fc_lport *lport = rdata->local_port; | 1307 | struct fc_lport *lport = rdata->local_port; |
1312 | struct fc_frame *fp; | 1308 | struct fc_frame *fp; |
1313 | struct fc_exch *ep = fc_seq_exch(sp); | ||
1314 | struct fc_els_adisc *adisc; | 1309 | struct fc_els_adisc *adisc; |
1315 | struct fc_seq_els_data rjt_data; | 1310 | struct fc_seq_els_data rjt_data; |
1316 | u32 f_ctl; | ||
1317 | 1311 | ||
1318 | FC_RPORT_DBG(rdata, "Received ADISC request\n"); | 1312 | FC_RPORT_DBG(rdata, "Received ADISC request\n"); |
1319 | 1313 | ||
@@ -1332,11 +1326,8 @@ static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, | |||
1332 | fc_adisc_fill(lport, fp); | 1326 | fc_adisc_fill(lport, fp); |
1333 | adisc = fc_frame_payload_get(fp, sizeof(*adisc)); | 1327 | adisc = fc_frame_payload_get(fp, sizeof(*adisc)); |
1334 | adisc->adisc_cmd = ELS_LS_ACC; | 1328 | adisc->adisc_cmd = ELS_LS_ACC; |
1335 | sp = lport->tt.seq_start_next(sp); | 1329 | fc_fill_reply_hdr(fp, in_fp, FC_RCTL_ELS_REP, 0); |
1336 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; | 1330 | lport->tt.frame_send(lport, fp); |
1337 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1338 | FC_TYPE_ELS, f_ctl, 0); | ||
1339 | lport->tt.seq_send(lport, sp, fp); | ||
1340 | drop: | 1331 | drop: |
1341 | fc_frame_free(in_fp); | 1332 | fc_frame_free(in_fp); |
1342 | } | 1333 | } |
@@ -1356,13 +1347,11 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, | |||
1356 | { | 1347 | { |
1357 | struct fc_lport *lport = rdata->local_port; | 1348 | struct fc_lport *lport = rdata->local_port; |
1358 | struct fc_frame *fp; | 1349 | struct fc_frame *fp; |
1359 | struct fc_exch *ep = fc_seq_exch(sp); | ||
1360 | struct fc_els_rls *rls; | 1350 | struct fc_els_rls *rls; |
1361 | struct fc_els_rls_resp *rsp; | 1351 | struct fc_els_rls_resp *rsp; |
1362 | struct fc_els_lesb *lesb; | 1352 | struct fc_els_lesb *lesb; |
1363 | struct fc_seq_els_data rjt_data; | 1353 | struct fc_seq_els_data rjt_data; |
1364 | struct fc_host_statistics *hst; | 1354 | struct fc_host_statistics *hst; |
1365 | u32 f_ctl; | ||
1366 | 1355 | ||
1367 | FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n", | 1356 | FC_RPORT_DBG(rdata, "Received RLS request while in state %s\n", |
1368 | fc_rport_state(rdata)); | 1357 | fc_rport_state(rdata)); |
@@ -1399,11 +1388,8 @@ static void fc_rport_recv_rls_req(struct fc_rport_priv *rdata, | |||
1399 | lesb->lesb_inv_crc = htonl(hst->invalid_crc_count); | 1388 | lesb->lesb_inv_crc = htonl(hst->invalid_crc_count); |
1400 | } | 1389 | } |
1401 | 1390 | ||
1402 | sp = lport->tt.seq_start_next(sp); | 1391 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
1403 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ; | 1392 | lport->tt.frame_send(lport, fp); |
1404 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1405 | FC_TYPE_ELS, f_ctl, 0); | ||
1406 | lport->tt.seq_send(lport, sp, fp); | ||
1407 | goto out; | 1393 | goto out; |
1408 | 1394 | ||
1409 | out_rjt: | 1395 | out_rjt: |
@@ -1549,10 +1535,9 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1549 | struct fc_disc *disc; | 1535 | struct fc_disc *disc; |
1550 | struct fc_rport_priv *rdata; | 1536 | struct fc_rport_priv *rdata; |
1551 | struct fc_frame *fp = rx_fp; | 1537 | struct fc_frame *fp = rx_fp; |
1552 | struct fc_exch *ep; | ||
1553 | struct fc_els_flogi *pl; | 1538 | struct fc_els_flogi *pl; |
1554 | struct fc_seq_els_data rjt_data; | 1539 | struct fc_seq_els_data rjt_data; |
1555 | u32 sid, f_ctl; | 1540 | u32 sid; |
1556 | 1541 | ||
1557 | rjt_data.fp = NULL; | 1542 | rjt_data.fp = NULL; |
1558 | sid = fc_frame_sid(fp); | 1543 | sid = fc_frame_sid(fp); |
@@ -1632,27 +1617,21 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, | |||
1632 | * Get session payload size from incoming PLOGI. | 1617 | * Get session payload size from incoming PLOGI. |
1633 | */ | 1618 | */ |
1634 | rdata->maxframe_size = fc_plogi_get_maxframe(pl, lport->mfs); | 1619 | rdata->maxframe_size = fc_plogi_get_maxframe(pl, lport->mfs); |
1635 | fc_frame_free(rx_fp); | ||
1636 | 1620 | ||
1637 | /* | 1621 | /* |
1638 | * Send LS_ACC. If this fails, the originator should retry. | 1622 | * Send LS_ACC. If this fails, the originator should retry. |
1639 | */ | 1623 | */ |
1640 | sp = lport->tt.seq_start_next(sp); | ||
1641 | if (!sp) | ||
1642 | goto out; | ||
1643 | fp = fc_frame_alloc(lport, sizeof(*pl)); | 1624 | fp = fc_frame_alloc(lport, sizeof(*pl)); |
1644 | if (!fp) | 1625 | if (!fp) |
1645 | goto out; | 1626 | goto out; |
1646 | 1627 | ||
1647 | fc_plogi_fill(lport, fp, ELS_LS_ACC); | 1628 | fc_plogi_fill(lport, fp, ELS_LS_ACC); |
1648 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; | 1629 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
1649 | ep = fc_seq_exch(sp); | 1630 | lport->tt.frame_send(lport, fp); |
1650 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1651 | FC_TYPE_ELS, f_ctl, 0); | ||
1652 | lport->tt.seq_send(lport, sp, fp); | ||
1653 | fc_rport_enter_prli(rdata); | 1631 | fc_rport_enter_prli(rdata); |
1654 | out: | 1632 | out: |
1655 | mutex_unlock(&rdata->rp_mutex); | 1633 | mutex_unlock(&rdata->rp_mutex); |
1634 | fc_frame_free(rx_fp); | ||
1656 | return; | 1635 | return; |
1657 | 1636 | ||
1658 | reject: | 1637 | reject: |
@@ -1673,7 +1652,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1673 | struct fc_seq *sp, struct fc_frame *rx_fp) | 1652 | struct fc_seq *sp, struct fc_frame *rx_fp) |
1674 | { | 1653 | { |
1675 | struct fc_lport *lport = rdata->local_port; | 1654 | struct fc_lport *lport = rdata->local_port; |
1676 | struct fc_exch *ep; | ||
1677 | struct fc_frame *fp; | 1655 | struct fc_frame *fp; |
1678 | struct { | 1656 | struct { |
1679 | struct fc_els_prli prli; | 1657 | struct fc_els_prli prli; |
@@ -1685,7 +1663,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1685 | unsigned int plen; | 1663 | unsigned int plen; |
1686 | enum fc_els_spp_resp resp; | 1664 | enum fc_els_spp_resp resp; |
1687 | struct fc_seq_els_data rjt_data; | 1665 | struct fc_seq_els_data rjt_data; |
1688 | u32 f_ctl; | ||
1689 | u32 fcp_parm; | 1666 | u32 fcp_parm; |
1690 | u32 roles = FC_RPORT_ROLE_UNKNOWN; | 1667 | u32 roles = FC_RPORT_ROLE_UNKNOWN; |
1691 | 1668 | ||
@@ -1714,8 +1691,6 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1714 | rjt_data.explan = ELS_EXPL_INSUF_RES; | 1691 | rjt_data.explan = ELS_EXPL_INSUF_RES; |
1715 | goto reject; | 1692 | goto reject; |
1716 | } | 1693 | } |
1717 | sp = lport->tt.seq_start_next(sp); | ||
1718 | WARN_ON(!sp); | ||
1719 | pp = fc_frame_payload_get(fp, len); | 1694 | pp = fc_frame_payload_get(fp, len); |
1720 | WARN_ON(!pp); | 1695 | WARN_ON(!pp); |
1721 | memset(pp, 0, len); | 1696 | memset(pp, 0, len); |
@@ -1768,12 +1743,8 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata, | |||
1768 | /* | 1743 | /* |
1769 | * Send LS_ACC. If this fails, the originator should retry. | 1744 | * Send LS_ACC. If this fails, the originator should retry. |
1770 | */ | 1745 | */ |
1771 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; | 1746 | fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_ELS_REP, 0); |
1772 | f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; | 1747 | lport->tt.frame_send(lport, fp); |
1773 | ep = fc_seq_exch(sp); | ||
1774 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1775 | FC_TYPE_ELS, f_ctl, 0); | ||
1776 | lport->tt.seq_send(lport, sp, fp); | ||
1777 | 1748 | ||
1778 | switch (rdata->rp_state) { | 1749 | switch (rdata->rp_state) { |
1779 | case RPORT_ST_PRLI: | 1750 | case RPORT_ST_PRLI: |
@@ -1817,7 +1788,6 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1817 | struct fc_els_spp *spp; /* response spp */ | 1788 | struct fc_els_spp *spp; /* response spp */ |
1818 | unsigned int len; | 1789 | unsigned int len; |
1819 | unsigned int plen; | 1790 | unsigned int plen; |
1820 | u32 f_ctl; | ||
1821 | struct fc_seq_els_data rjt_data; | 1791 | struct fc_seq_els_data rjt_data; |
1822 | 1792 | ||
1823 | rjt_data.fp = NULL; | 1793 | rjt_data.fp = NULL; |
@@ -1859,11 +1829,9 @@ static void fc_rport_recv_prlo_req(struct fc_rport_priv *rdata, | |||
1859 | 1829 | ||
1860 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); | 1830 | fc_rport_enter_delete(rdata, RPORT_EV_LOGO); |
1861 | 1831 | ||
1862 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; | ||
1863 | f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; | ||
1864 | ep = fc_seq_exch(sp); | 1832 | ep = fc_seq_exch(sp); |
1865 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | 1833 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, |
1866 | FC_TYPE_ELS, f_ctl, 0); | 1834 | FC_TYPE_ELS, FC_FCTL_RESP, 0); |
1867 | lport->tt.seq_send(lport, sp, fp); | 1835 | lport->tt.seq_send(lport, sp, fp); |
1868 | goto drop; | 1836 | goto drop; |
1869 | 1837 | ||
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index 9b4867c9c2d2..6d293c846a46 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h | |||
@@ -21,6 +21,13 @@ | |||
21 | #define _FC_ENCODE_H_ | 21 | #define _FC_ENCODE_H_ |
22 | #include <asm/unaligned.h> | 22 | #include <asm/unaligned.h> |
23 | 23 | ||
24 | /* | ||
25 | * F_CTL values for simple requests and responses. | ||
26 | */ | ||
27 | #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT) | ||
28 | #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \ | ||
29 | FC_FC_END_SEQ | FC_FC_SEQ_INIT) | ||
30 | |||
24 | struct fc_ns_rft { | 31 | struct fc_ns_rft { |
25 | struct fc_ns_fid fid; /* port ID object */ | 32 | struct fc_ns_fid fid; /* port ID object */ |
26 | struct fc_ns_fts fts; /* FC4-types object */ | 33 | struct fc_ns_fts fts; /* FC4-types object */ |
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index f1ce793f33b3..a6414ec63809 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h | |||
@@ -1027,6 +1027,10 @@ struct fc_seq *fc_elsct_send(struct fc_lport *, u32 did, | |||
1027 | void *arg, u32 timer_msec); | 1027 | void *arg, u32 timer_msec); |
1028 | void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); | 1028 | void fc_lport_flogi_resp(struct fc_seq *, struct fc_frame *, void *); |
1029 | void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); | 1029 | void fc_lport_logo_resp(struct fc_seq *, struct fc_frame *, void *); |
1030 | void fc_fill_reply_hdr(struct fc_frame *, const struct fc_frame *, | ||
1031 | enum fc_rctl, u32 parm_offset); | ||
1032 | void fc_fill_hdr(struct fc_frame *, const struct fc_frame *, | ||
1033 | enum fc_rctl, u32 f_ctl, u16 seq_cnt, u32 parm_offset); | ||
1030 | 1034 | ||
1031 | 1035 | ||
1032 | /* | 1036 | /* |