Commit 1ea2c1daf4476ac798b1de8196f11dd36425b5ae

Authored by Neerav Parikh
Committed by James Bottomley
1 parent a9277e7783

[SCSI] libfc: Make the libfc Common Transport(CT) code generic

Currently the libfc Common Transport(CT) calls assume that
the CT requests are Name Server specific only. This patch
makes it more flexible to allow more FC-GS services to make
use of these routines.

Signed-off-by: Neerav Parikh <neerav.parikh@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Acked-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 2 changed files with 49 additions and 14 deletions Inline Diff

drivers/scsi/libfc/fc_elsct.c
1 /* 1 /*
2 * Copyright(c) 2008 Intel Corporation. All rights reserved. 2 * Copyright(c) 2008 Intel Corporation. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation. 6 * version 2, as published by the Free Software Foundation.
7 * 7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT 8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details. 11 * more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License along with 13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 * 16 *
17 * Maintained at www.Open-FCoE.org 17 * Maintained at www.Open-FCoE.org
18 */ 18 */
19 19
20 /* 20 /*
21 * Provide interface to send ELS/CT FC frames 21 * Provide interface to send ELS/CT FC frames
22 */ 22 */
23 23
24 #include <linux/export.h> 24 #include <linux/export.h>
25 #include <asm/unaligned.h> 25 #include <asm/unaligned.h>
26 #include <scsi/fc/fc_gs.h> 26 #include <scsi/fc/fc_gs.h>
27 #include <scsi/fc/fc_ns.h> 27 #include <scsi/fc/fc_ns.h>
28 #include <scsi/fc/fc_els.h> 28 #include <scsi/fc/fc_els.h>
29 #include <scsi/libfc.h> 29 #include <scsi/libfc.h>
30 #include <scsi/fc_encode.h> 30 #include <scsi/fc_encode.h>
31 #include "fc_libfc.h" 31 #include "fc_libfc.h"
32 32
33 /** 33 /**
34 * fc_elsct_send() - Send an ELS or CT frame 34 * fc_elsct_send() - Send an ELS or CT frame
35 * @lport: The local port to send the frame on 35 * @lport: The local port to send the frame on
36 * @did: The destination ID for the frame 36 * @did: The destination ID for the frame
37 * @fp: The frame to be sent 37 * @fp: The frame to be sent
38 * @op: The operational code 38 * @op: The operational code
39 * @resp: The callback routine when the response is received 39 * @resp: The callback routine when the response is received
40 * @arg: The argument to pass to the response callback routine 40 * @arg: The argument to pass to the response callback routine
41 * @timer_msec: The timeout period for the frame (in msecs) 41 * @timer_msec: The timeout period for the frame (in msecs)
42 */ 42 */
43 struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, 43 struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did,
44 struct fc_frame *fp, unsigned int op, 44 struct fc_frame *fp, unsigned int op,
45 void (*resp)(struct fc_seq *, 45 void (*resp)(struct fc_seq *,
46 struct fc_frame *, 46 struct fc_frame *,
47 void *), 47 void *),
48 void *arg, u32 timer_msec) 48 void *arg, u32 timer_msec)
49 { 49 {
50 enum fc_rctl r_ctl; 50 enum fc_rctl r_ctl;
51 enum fc_fh_type fh_type; 51 enum fc_fh_type fh_type;
52 int rc; 52 int rc;
53 53
54 /* ELS requests */ 54 /* ELS requests */
55 if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) 55 if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS))
56 rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type); 56 rc = fc_els_fill(lport, did, fp, op, &r_ctl, &fh_type);
57 else { 57 else {
58 /* CT requests */ 58 /* CT requests */
59 rc = fc_ct_fill(lport, did, fp, op, &r_ctl, &fh_type); 59 rc = fc_ct_fill(lport, did, fp, op, &r_ctl, &fh_type, &did);
60 did = FC_FID_DIR_SERV;
61 } 60 }
62 61
63 if (rc) { 62 if (rc) {
64 fc_frame_free(fp); 63 fc_frame_free(fp);
65 return NULL; 64 return NULL;
66 } 65 }
67 66
68 fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type, 67 fc_fill_fc_hdr(fp, r_ctl, did, lport->port_id, fh_type,
69 FC_FCTL_REQ, 0); 68 FC_FCTL_REQ, 0);
70 69
71 return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec); 70 return lport->tt.exch_seq_send(lport, fp, resp, NULL, arg, timer_msec);
72 } 71 }
73 EXPORT_SYMBOL(fc_elsct_send); 72 EXPORT_SYMBOL(fc_elsct_send);
74 73
75 /** 74 /**
76 * fc_elsct_init() - Initialize the ELS/CT layer 75 * fc_elsct_init() - Initialize the ELS/CT layer
77 * @lport: The local port to initialize the ELS/CT layer for 76 * @lport: The local port to initialize the ELS/CT layer for
78 */ 77 */
79 int fc_elsct_init(struct fc_lport *lport) 78 int fc_elsct_init(struct fc_lport *lport)
80 { 79 {
81 if (!lport->tt.elsct_send) 80 if (!lport->tt.elsct_send)
82 lport->tt.elsct_send = fc_elsct_send; 81 lport->tt.elsct_send = fc_elsct_send;
83 82
84 return 0; 83 return 0;
85 } 84 }
86 EXPORT_SYMBOL(fc_elsct_init); 85 EXPORT_SYMBOL(fc_elsct_init);
87 86
88 /** 87 /**
89 * fc_els_resp_type() - Return a string describing the ELS response 88 * fc_els_resp_type() - Return a string describing the ELS response
90 * @fp: The frame pointer or possible error code 89 * @fp: The frame pointer or possible error code
91 */ 90 */
92 const char *fc_els_resp_type(struct fc_frame *fp) 91 const char *fc_els_resp_type(struct fc_frame *fp)
93 { 92 {
94 const char *msg; 93 const char *msg;
95 struct fc_frame_header *fh; 94 struct fc_frame_header *fh;
96 struct fc_ct_hdr *ct; 95 struct fc_ct_hdr *ct;
97 96
98 if (IS_ERR(fp)) { 97 if (IS_ERR(fp)) {
99 switch (-PTR_ERR(fp)) { 98 switch (-PTR_ERR(fp)) {
100 case FC_NO_ERR: 99 case FC_NO_ERR:
101 msg = "response no error"; 100 msg = "response no error";
102 break; 101 break;
103 case FC_EX_TIMEOUT: 102 case FC_EX_TIMEOUT:
104 msg = "response timeout"; 103 msg = "response timeout";
105 break; 104 break;
106 case FC_EX_CLOSED: 105 case FC_EX_CLOSED:
107 msg = "response closed"; 106 msg = "response closed";
108 break; 107 break;
109 default: 108 default:
110 msg = "response unknown error"; 109 msg = "response unknown error";
111 break; 110 break;
112 } 111 }
113 } else { 112 } else {
114 fh = fc_frame_header_get(fp); 113 fh = fc_frame_header_get(fp);
115 switch (fh->fh_type) { 114 switch (fh->fh_type) {
116 case FC_TYPE_ELS: 115 case FC_TYPE_ELS:
117 switch (fc_frame_payload_op(fp)) { 116 switch (fc_frame_payload_op(fp)) {
118 case ELS_LS_ACC: 117 case ELS_LS_ACC:
119 msg = "accept"; 118 msg = "accept";
120 break; 119 break;
121 case ELS_LS_RJT: 120 case ELS_LS_RJT:
122 msg = "reject"; 121 msg = "reject";
123 break; 122 break;
124 default: 123 default:
125 msg = "response unknown ELS"; 124 msg = "response unknown ELS";
126 break; 125 break;
127 } 126 }
128 break; 127 break;
129 case FC_TYPE_CT: 128 case FC_TYPE_CT:
130 ct = fc_frame_payload_get(fp, sizeof(*ct)); 129 ct = fc_frame_payload_get(fp, sizeof(*ct));
131 if (ct) { 130 if (ct) {
132 switch (ntohs(ct->ct_cmd)) { 131 switch (ntohs(ct->ct_cmd)) {
133 case FC_FS_ACC: 132 case FC_FS_ACC:
134 msg = "CT accept"; 133 msg = "CT accept";
135 break; 134 break;
136 case FC_FS_RJT: 135 case FC_FS_RJT:
137 msg = "CT reject"; 136 msg = "CT reject";
138 break; 137 break;
139 default: 138 default:
140 msg = "response unknown CT"; 139 msg = "response unknown CT";
141 break; 140 break;
142 } 141 }
143 } else { 142 } else {
144 msg = "short CT response"; 143 msg = "short CT response";
145 } 144 }
146 break; 145 break;
147 default: 146 default:
148 msg = "response not ELS or CT"; 147 msg = "response not ELS or CT";
149 break; 148 break;
150 } 149 }
151 } 150 }
152 return msg; 151 return msg;
153 } 152 }
154 153
include/scsi/fc_encode.h
1 /* 1 /*
2 * Copyright(c) 2008 Intel Corporation. All rights reserved. 2 * Copyright(c) 2008 Intel Corporation. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation. 6 * version 2, as published by the Free Software Foundation.
7 * 7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT 8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details. 11 * more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License along with 13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 * 16 *
17 * Maintained at www.Open-FCoE.org 17 * Maintained at www.Open-FCoE.org
18 */ 18 */
19 19
20 #ifndef _FC_ENCODE_H_ 20 #ifndef _FC_ENCODE_H_
21 #define _FC_ENCODE_H_ 21 #define _FC_ENCODE_H_
22 #include <asm/unaligned.h> 22 #include <asm/unaligned.h>
23 23
24 /* 24 /*
25 * F_CTL values for simple requests and responses. 25 * F_CTL values for simple requests and responses.
26 */ 26 */
27 #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT) 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 | \ 28 #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
29 FC_FC_END_SEQ | FC_FC_SEQ_INIT) 29 FC_FC_END_SEQ | FC_FC_SEQ_INIT)
30 30
31 struct fc_ns_rft { 31 struct fc_ns_rft {
32 struct fc_ns_fid fid; /* port ID object */ 32 struct fc_ns_fid fid; /* port ID object */
33 struct fc_ns_fts fts; /* FC4-types object */ 33 struct fc_ns_fts fts; /* FC4-types object */
34 }; 34 };
35 35
36 struct fc_ct_req { 36 struct fc_ct_req {
37 struct fc_ct_hdr hdr; 37 struct fc_ct_hdr hdr;
38 union { 38 union {
39 struct fc_ns_gid_ft gid; 39 struct fc_ns_gid_ft gid;
40 struct fc_ns_rn_id rn; 40 struct fc_ns_rn_id rn;
41 struct fc_ns_rft rft; 41 struct fc_ns_rft rft;
42 struct fc_ns_rff_id rff; 42 struct fc_ns_rff_id rff;
43 struct fc_ns_fid fid; 43 struct fc_ns_fid fid;
44 struct fc_ns_rsnn snn; 44 struct fc_ns_rsnn snn;
45 struct fc_ns_rspn spn; 45 struct fc_ns_rspn spn;
46 } payload; 46 } payload;
47 }; 47 };
48 48
49 static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh, 49 static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
50 enum fc_rctl r_ctl, 50 enum fc_rctl r_ctl,
51 u32 did, u32 sid, enum fc_fh_type type, 51 u32 did, u32 sid, enum fc_fh_type type,
52 u32 f_ctl, u32 parm_offset) 52 u32 f_ctl, u32 parm_offset)
53 { 53 {
54 WARN_ON(r_ctl == 0); 54 WARN_ON(r_ctl == 0);
55 fh->fh_r_ctl = r_ctl; 55 fh->fh_r_ctl = r_ctl;
56 hton24(fh->fh_d_id, did); 56 hton24(fh->fh_d_id, did);
57 hton24(fh->fh_s_id, sid); 57 hton24(fh->fh_s_id, sid);
58 fh->fh_type = type; 58 fh->fh_type = type;
59 hton24(fh->fh_f_ctl, f_ctl); 59 hton24(fh->fh_f_ctl, f_ctl);
60 fh->fh_cs_ctl = 0; 60 fh->fh_cs_ctl = 0;
61 fh->fh_df_ctl = 0; 61 fh->fh_df_ctl = 0;
62 fh->fh_parm_offset = htonl(parm_offset); 62 fh->fh_parm_offset = htonl(parm_offset);
63 } 63 }
64 64
65 /** 65 /**
66 * fill FC header fields in specified fc_frame 66 * fill FC header fields in specified fc_frame
67 */ 67 */
68 static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl, 68 static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
69 u32 did, u32 sid, enum fc_fh_type type, 69 u32 did, u32 sid, enum fc_fh_type type,
70 u32 f_ctl, u32 parm_offset) 70 u32 f_ctl, u32 parm_offset)
71 { 71 {
72 struct fc_frame_header *fh; 72 struct fc_frame_header *fh;
73 73
74 fh = fc_frame_header_get(fp); 74 fh = fc_frame_header_get(fp);
75 __fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset); 75 __fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset);
76 } 76 }
77 77
78 /** 78 /**
79 * fc_adisc_fill() - Fill in adisc request frame 79 * fc_adisc_fill() - Fill in adisc request frame
80 * @lport: local port. 80 * @lport: local port.
81 * @fp: fc frame where payload will be placed. 81 * @fp: fc frame where payload will be placed.
82 */ 82 */
83 static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp) 83 static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
84 { 84 {
85 struct fc_els_adisc *adisc; 85 struct fc_els_adisc *adisc;
86 86
87 adisc = fc_frame_payload_get(fp, sizeof(*adisc)); 87 adisc = fc_frame_payload_get(fp, sizeof(*adisc));
88 memset(adisc, 0, sizeof(*adisc)); 88 memset(adisc, 0, sizeof(*adisc));
89 adisc->adisc_cmd = ELS_ADISC; 89 adisc->adisc_cmd = ELS_ADISC;
90 put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn); 90 put_unaligned_be64(lport->wwpn, &adisc->adisc_wwpn);
91 put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn); 91 put_unaligned_be64(lport->wwnn, &adisc->adisc_wwnn);
92 hton24(adisc->adisc_port_id, lport->port_id); 92 hton24(adisc->adisc_port_id, lport->port_id);
93 } 93 }
94 94
95 /** 95 /**
96 * fc_ct_hdr_fill- fills ct header and reset ct payload 96 * fc_ct_hdr_fill- fills ct header and reset ct payload
97 * returns pointer to ct request. 97 * returns pointer to ct request.
98 */ 98 */
99 static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, 99 static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp,
100 unsigned int op, size_t req_size) 100 unsigned int op, size_t req_size,
101 enum fc_ct_fs_type fs_type,
102 u8 subtype)
101 { 103 {
102 struct fc_ct_req *ct; 104 struct fc_ct_req *ct;
103 size_t ct_plen; 105 size_t ct_plen;
104 106
105 ct_plen = sizeof(struct fc_ct_hdr) + req_size; 107 ct_plen = sizeof(struct fc_ct_hdr) + req_size;
106 ct = fc_frame_payload_get(fp, ct_plen); 108 ct = fc_frame_payload_get(fp, ct_plen);
107 memset(ct, 0, ct_plen); 109 memset(ct, 0, ct_plen);
108 ct->hdr.ct_rev = FC_CT_REV; 110 ct->hdr.ct_rev = FC_CT_REV;
109 ct->hdr.ct_fs_type = FC_FST_DIR; 111 ct->hdr.ct_fs_type = fs_type;
110 ct->hdr.ct_fs_subtype = FC_NS_SUBTYPE; 112 ct->hdr.ct_fs_subtype = subtype;
111 ct->hdr.ct_cmd = htons((u16) op); 113 ct->hdr.ct_cmd = htons((u16) op);
112 return ct; 114 return ct;
113 } 115 }
114 116
115 /** 117 /**
116 * fc_ct_fill() - Fill in a name service request frame 118 * fc_ct_ns_fill() - Fill in a name service request frame
117 * @lport: local port. 119 * @lport: local port.
118 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries. 120 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
119 * @fp: frame to contain payload. 121 * @fp: frame to contain payload.
120 * @op: CT opcode. 122 * @op: CT opcode.
121 * @r_ctl: pointer to FC header R_CTL. 123 * @r_ctl: pointer to FC header R_CTL.
122 * @fh_type: pointer to FC-4 type. 124 * @fh_type: pointer to FC-4 type.
123 */ 125 */
124 static inline int fc_ct_fill(struct fc_lport *lport, 126 static inline int fc_ct_ns_fill(struct fc_lport *lport,
125 u32 fc_id, struct fc_frame *fp, 127 u32 fc_id, struct fc_frame *fp,
126 unsigned int op, enum fc_rctl *r_ctl, 128 unsigned int op, enum fc_rctl *r_ctl,
127 enum fc_fh_type *fh_type) 129 enum fc_fh_type *fh_type)
128 { 130 {
129 struct fc_ct_req *ct; 131 struct fc_ct_req *ct;
130 size_t len; 132 size_t len;
131 133
132 switch (op) { 134 switch (op) {
133 case FC_NS_GPN_FT: 135 case FC_NS_GPN_FT:
134 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft)); 136 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_gid_ft),
137 FC_FST_DIR, FC_NS_SUBTYPE);
135 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP; 138 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
136 break; 139 break;
137 140
138 case FC_NS_GPN_ID: 141 case FC_NS_GPN_ID:
139 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid)); 142 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_fid),
143 FC_FST_DIR, FC_NS_SUBTYPE);
144 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
140 hton24(ct->payload.fid.fp_fid, fc_id); 145 hton24(ct->payload.fid.fp_fid, fc_id);
141 break; 146 break;
142 147
143 case FC_NS_RFT_ID: 148 case FC_NS_RFT_ID:
144 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft)); 149 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rft),
150 FC_FST_DIR, FC_NS_SUBTYPE);
145 hton24(ct->payload.rft.fid.fp_fid, lport->port_id); 151 hton24(ct->payload.rft.fid.fp_fid, lport->port_id);
146 ct->payload.rft.fts = lport->fcts; 152 ct->payload.rft.fts = lport->fcts;
147 break; 153 break;
148 154
149 case FC_NS_RFF_ID: 155 case FC_NS_RFF_ID:
150 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id)); 156 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rff_id),
157 FC_FST_DIR, FC_NS_SUBTYPE);
151 hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id); 158 hton24(ct->payload.rff.fr_fid.fp_fid, lport->port_id);
152 ct->payload.rff.fr_type = FC_TYPE_FCP; 159 ct->payload.rff.fr_type = FC_TYPE_FCP;
153 if (lport->service_params & FCP_SPPF_INIT_FCN) 160 if (lport->service_params & FCP_SPPF_INIT_FCN)
154 ct->payload.rff.fr_feat = FCP_FEAT_INIT; 161 ct->payload.rff.fr_feat = FCP_FEAT_INIT;
155 if (lport->service_params & FCP_SPPF_TARG_FCN) 162 if (lport->service_params & FCP_SPPF_TARG_FCN)
156 ct->payload.rff.fr_feat |= FCP_FEAT_TARG; 163 ct->payload.rff.fr_feat |= FCP_FEAT_TARG;
157 break; 164 break;
158 165
159 case FC_NS_RNN_ID: 166 case FC_NS_RNN_ID:
160 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id)); 167 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rn_id),
168 FC_FST_DIR, FC_NS_SUBTYPE);
161 hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id); 169 hton24(ct->payload.rn.fr_fid.fp_fid, lport->port_id);
162 put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn); 170 put_unaligned_be64(lport->wwnn, &ct->payload.rn.fr_wwn);
163 break; 171 break;
164 172
165 case FC_NS_RSPN_ID: 173 case FC_NS_RSPN_ID:
166 len = strnlen(fc_host_symbolic_name(lport->host), 255); 174 len = strnlen(fc_host_symbolic_name(lport->host), 255);
167 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len); 175 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rspn) + len,
176 FC_FST_DIR, FC_NS_SUBTYPE);
168 hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id); 177 hton24(ct->payload.spn.fr_fid.fp_fid, lport->port_id);
169 strncpy(ct->payload.spn.fr_name, 178 strncpy(ct->payload.spn.fr_name,
170 fc_host_symbolic_name(lport->host), len); 179 fc_host_symbolic_name(lport->host), len);
171 ct->payload.spn.fr_name_len = len; 180 ct->payload.spn.fr_name_len = len;
172 break; 181 break;
173 182
174 case FC_NS_RSNN_NN: 183 case FC_NS_RSNN_NN:
175 len = strnlen(fc_host_symbolic_name(lport->host), 255); 184 len = strnlen(fc_host_symbolic_name(lport->host), 255);
176 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len); 185 ct = fc_ct_hdr_fill(fp, op, sizeof(struct fc_ns_rsnn) + len,
186 FC_FST_DIR, FC_NS_SUBTYPE);
177 put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn); 187 put_unaligned_be64(lport->wwnn, &ct->payload.snn.fr_wwn);
178 strncpy(ct->payload.snn.fr_name, 188 strncpy(ct->payload.snn.fr_name,
179 fc_host_symbolic_name(lport->host), len); 189 fc_host_symbolic_name(lport->host), len);
180 ct->payload.snn.fr_name_len = len; 190 ct->payload.snn.fr_name_len = len;
181 break; 191 break;
182 192
183 default: 193 default:
184 return -EINVAL; 194 return -EINVAL;
185 } 195 }
186 *r_ctl = FC_RCTL_DD_UNSOL_CTL; 196 *r_ctl = FC_RCTL_DD_UNSOL_CTL;
187 *fh_type = FC_TYPE_CT; 197 *fh_type = FC_TYPE_CT;
188 return 0; 198 return 0;
189 } 199 }
190 200
201 /**
202 * fc_ct_fill() - Fill in a common transport service request frame
203 * @lport: local port.
204 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
205 * @fp: frame to contain payload.
206 * @op: CT opcode.
207 * @r_ctl: pointer to FC header R_CTL.
208 * @fh_type: pointer to FC-4 type.
209 */
210 static inline int fc_ct_fill(struct fc_lport *lport,
211 u32 fc_id, struct fc_frame *fp,
212 unsigned int op, enum fc_rctl *r_ctl,
213 enum fc_fh_type *fh_type, u32 *did)
214 {
215 int rc = -EINVAL;
216
217 switch (fc_id) {
218 case FC_FID_DIR_SERV:
219 default:
220 rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
221 *did = FC_FID_DIR_SERV;
222 break;
223 }
224
225 return rc;
226 }
191 /** 227 /**
192 * fc_plogi_fill - Fill in plogi request frame 228 * fc_plogi_fill - Fill in plogi request frame
193 */ 229 */
194 static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp, 230 static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
195 unsigned int op) 231 unsigned int op)
196 { 232 {
197 struct fc_els_flogi *plogi; 233 struct fc_els_flogi *plogi;
198 struct fc_els_csp *csp; 234 struct fc_els_csp *csp;
199 struct fc_els_cssp *cp; 235 struct fc_els_cssp *cp;
200 236
201 plogi = fc_frame_payload_get(fp, sizeof(*plogi)); 237 plogi = fc_frame_payload_get(fp, sizeof(*plogi));
202 memset(plogi, 0, sizeof(*plogi)); 238 memset(plogi, 0, sizeof(*plogi));
203 plogi->fl_cmd = (u8) op; 239 plogi->fl_cmd = (u8) op;
204 put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn); 240 put_unaligned_be64(lport->wwpn, &plogi->fl_wwpn);
205 put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn); 241 put_unaligned_be64(lport->wwnn, &plogi->fl_wwnn);
206 242
207 csp = &plogi->fl_csp; 243 csp = &plogi->fl_csp;
208 csp->sp_hi_ver = 0x20; 244 csp->sp_hi_ver = 0x20;
209 csp->sp_lo_ver = 0x20; 245 csp->sp_lo_ver = 0x20;
210 csp->sp_bb_cred = htons(10); /* this gets set by gateway */ 246 csp->sp_bb_cred = htons(10); /* this gets set by gateway */
211 csp->sp_bb_data = htons((u16) lport->mfs); 247 csp->sp_bb_data = htons((u16) lport->mfs);
212 cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */ 248 cp = &plogi->fl_cssp[3 - 1]; /* class 3 parameters */
213 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); 249 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
214 csp->sp_features = htons(FC_SP_FT_CIRO); 250 csp->sp_features = htons(FC_SP_FT_CIRO);
215 csp->sp_tot_seq = htons(255); /* seq. we accept */ 251 csp->sp_tot_seq = htons(255); /* seq. we accept */
216 csp->sp_rel_off = htons(0x1f); 252 csp->sp_rel_off = htons(0x1f);
217 csp->sp_e_d_tov = htonl(lport->e_d_tov); 253 csp->sp_e_d_tov = htonl(lport->e_d_tov);
218 254
219 cp->cp_rdfs = htons((u16) lport->mfs); 255 cp->cp_rdfs = htons((u16) lport->mfs);
220 cp->cp_con_seq = htons(255); 256 cp->cp_con_seq = htons(255);
221 cp->cp_open_seq = 1; 257 cp->cp_open_seq = 1;
222 } 258 }
223 259
224 /** 260 /**
225 * fc_flogi_fill - Fill in a flogi request frame. 261 * fc_flogi_fill - Fill in a flogi request frame.
226 */ 262 */
227 static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp) 263 static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
228 { 264 {
229 struct fc_els_csp *sp; 265 struct fc_els_csp *sp;
230 struct fc_els_cssp *cp; 266 struct fc_els_cssp *cp;
231 struct fc_els_flogi *flogi; 267 struct fc_els_flogi *flogi;
232 268
233 flogi = fc_frame_payload_get(fp, sizeof(*flogi)); 269 flogi = fc_frame_payload_get(fp, sizeof(*flogi));
234 memset(flogi, 0, sizeof(*flogi)); 270 memset(flogi, 0, sizeof(*flogi));
235 flogi->fl_cmd = (u8) ELS_FLOGI; 271 flogi->fl_cmd = (u8) ELS_FLOGI;
236 put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn); 272 put_unaligned_be64(lport->wwpn, &flogi->fl_wwpn);
237 put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn); 273 put_unaligned_be64(lport->wwnn, &flogi->fl_wwnn);
238 sp = &flogi->fl_csp; 274 sp = &flogi->fl_csp;
239 sp->sp_hi_ver = 0x20; 275 sp->sp_hi_ver = 0x20;
240 sp->sp_lo_ver = 0x20; 276 sp->sp_lo_ver = 0x20;
241 sp->sp_bb_cred = htons(10); /* this gets set by gateway */ 277 sp->sp_bb_cred = htons(10); /* this gets set by gateway */
242 sp->sp_bb_data = htons((u16) lport->mfs); 278 sp->sp_bb_data = htons((u16) lport->mfs);
243 cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */ 279 cp = &flogi->fl_cssp[3 - 1]; /* class 3 parameters */
244 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); 280 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
245 if (lport->does_npiv) 281 if (lport->does_npiv)
246 sp->sp_features = htons(FC_SP_FT_NPIV); 282 sp->sp_features = htons(FC_SP_FT_NPIV);
247 } 283 }
248 284
249 /** 285 /**
250 * fc_fdisc_fill - Fill in a fdisc request frame. 286 * fc_fdisc_fill - Fill in a fdisc request frame.
251 */ 287 */
252 static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp) 288 static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
253 { 289 {
254 struct fc_els_csp *sp; 290 struct fc_els_csp *sp;
255 struct fc_els_cssp *cp; 291 struct fc_els_cssp *cp;
256 struct fc_els_flogi *fdisc; 292 struct fc_els_flogi *fdisc;
257 293
258 fdisc = fc_frame_payload_get(fp, sizeof(*fdisc)); 294 fdisc = fc_frame_payload_get(fp, sizeof(*fdisc));
259 memset(fdisc, 0, sizeof(*fdisc)); 295 memset(fdisc, 0, sizeof(*fdisc));
260 fdisc->fl_cmd = (u8) ELS_FDISC; 296 fdisc->fl_cmd = (u8) ELS_FDISC;
261 put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn); 297 put_unaligned_be64(lport->wwpn, &fdisc->fl_wwpn);
262 put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn); 298 put_unaligned_be64(lport->wwnn, &fdisc->fl_wwnn);
263 sp = &fdisc->fl_csp; 299 sp = &fdisc->fl_csp;
264 sp->sp_hi_ver = 0x20; 300 sp->sp_hi_ver = 0x20;
265 sp->sp_lo_ver = 0x20; 301 sp->sp_lo_ver = 0x20;
266 sp->sp_bb_cred = htons(10); /* this gets set by gateway */ 302 sp->sp_bb_cred = htons(10); /* this gets set by gateway */
267 sp->sp_bb_data = htons((u16) lport->mfs); 303 sp->sp_bb_data = htons((u16) lport->mfs);
268 cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */ 304 cp = &fdisc->fl_cssp[3 - 1]; /* class 3 parameters */
269 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ); 305 cp->cp_class = htons(FC_CPC_VALID | FC_CPC_SEQ);
270 } 306 }
271 307
272 /** 308 /**
273 * fc_logo_fill - Fill in a logo request frame. 309 * fc_logo_fill - Fill in a logo request frame.
274 */ 310 */
275 static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp) 311 static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
276 { 312 {
277 struct fc_els_logo *logo; 313 struct fc_els_logo *logo;
278 314
279 logo = fc_frame_payload_get(fp, sizeof(*logo)); 315 logo = fc_frame_payload_get(fp, sizeof(*logo));
280 memset(logo, 0, sizeof(*logo)); 316 memset(logo, 0, sizeof(*logo));
281 logo->fl_cmd = ELS_LOGO; 317 logo->fl_cmd = ELS_LOGO;
282 hton24(logo->fl_n_port_id, lport->port_id); 318 hton24(logo->fl_n_port_id, lport->port_id);
283 logo->fl_n_port_wwn = htonll(lport->wwpn); 319 logo->fl_n_port_wwn = htonll(lport->wwpn);
284 } 320 }
285 321
286 /** 322 /**
287 * fc_rtv_fill - Fill in RTV (read timeout value) request frame. 323 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
288 */ 324 */
289 static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp) 325 static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
290 { 326 {
291 struct fc_els_rtv *rtv; 327 struct fc_els_rtv *rtv;
292 328
293 rtv = fc_frame_payload_get(fp, sizeof(*rtv)); 329 rtv = fc_frame_payload_get(fp, sizeof(*rtv));
294 memset(rtv, 0, sizeof(*rtv)); 330 memset(rtv, 0, sizeof(*rtv));
295 rtv->rtv_cmd = ELS_RTV; 331 rtv->rtv_cmd = ELS_RTV;
296 } 332 }
297 333
298 /** 334 /**
299 * fc_rec_fill - Fill in rec request frame 335 * fc_rec_fill - Fill in rec request frame
300 */ 336 */
301 static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp) 337 static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
302 { 338 {
303 struct fc_els_rec *rec; 339 struct fc_els_rec *rec;
304 struct fc_exch *ep = fc_seq_exch(fr_seq(fp)); 340 struct fc_exch *ep = fc_seq_exch(fr_seq(fp));
305 341
306 rec = fc_frame_payload_get(fp, sizeof(*rec)); 342 rec = fc_frame_payload_get(fp, sizeof(*rec));
307 memset(rec, 0, sizeof(*rec)); 343 memset(rec, 0, sizeof(*rec));
308 rec->rec_cmd = ELS_REC; 344 rec->rec_cmd = ELS_REC;
309 hton24(rec->rec_s_id, lport->port_id); 345 hton24(rec->rec_s_id, lport->port_id);
310 rec->rec_ox_id = htons(ep->oxid); 346 rec->rec_ox_id = htons(ep->oxid);
311 rec->rec_rx_id = htons(ep->rxid); 347 rec->rec_rx_id = htons(ep->rxid);
312 } 348 }
313 349
314 /** 350 /**
315 * fc_prli_fill - Fill in prli request frame 351 * fc_prli_fill - Fill in prli request frame
316 */ 352 */
317 static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp) 353 static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
318 { 354 {
319 struct { 355 struct {
320 struct fc_els_prli prli; 356 struct fc_els_prli prli;
321 struct fc_els_spp spp; 357 struct fc_els_spp spp;
322 } *pp; 358 } *pp;
323 359
324 pp = fc_frame_payload_get(fp, sizeof(*pp)); 360 pp = fc_frame_payload_get(fp, sizeof(*pp));
325 memset(pp, 0, sizeof(*pp)); 361 memset(pp, 0, sizeof(*pp));
326 pp->prli.prli_cmd = ELS_PRLI; 362 pp->prli.prli_cmd = ELS_PRLI;
327 pp->prli.prli_spp_len = sizeof(struct fc_els_spp); 363 pp->prli.prli_spp_len = sizeof(struct fc_els_spp);
328 pp->prli.prli_len = htons(sizeof(*pp)); 364 pp->prli.prli_len = htons(sizeof(*pp));
329 pp->spp.spp_type = FC_TYPE_FCP; 365 pp->spp.spp_type = FC_TYPE_FCP;
330 pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR; 366 pp->spp.spp_flags = FC_SPP_EST_IMG_PAIR;
331 pp->spp.spp_params = htonl(lport->service_params); 367 pp->spp.spp_params = htonl(lport->service_params);
332 } 368 }
333 369
334 /** 370 /**
335 * fc_scr_fill - Fill in a scr request frame. 371 * fc_scr_fill - Fill in a scr request frame.
336 */ 372 */
337 static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp) 373 static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
338 { 374 {
339 struct fc_els_scr *scr; 375 struct fc_els_scr *scr;
340 376
341 scr = fc_frame_payload_get(fp, sizeof(*scr)); 377 scr = fc_frame_payload_get(fp, sizeof(*scr));
342 memset(scr, 0, sizeof(*scr)); 378 memset(scr, 0, sizeof(*scr));
343 scr->scr_cmd = ELS_SCR; 379 scr->scr_cmd = ELS_SCR;
344 scr->scr_reg_func = ELS_SCRF_FULL; 380 scr->scr_reg_func = ELS_SCRF_FULL;
345 } 381 }
346 382
347 /** 383 /**
348 * fc_els_fill - Fill in an ELS request frame 384 * fc_els_fill - Fill in an ELS request frame
349 */ 385 */
350 static inline int fc_els_fill(struct fc_lport *lport, 386 static inline int fc_els_fill(struct fc_lport *lport,
351 u32 did, 387 u32 did,
352 struct fc_frame *fp, unsigned int op, 388 struct fc_frame *fp, unsigned int op,
353 enum fc_rctl *r_ctl, enum fc_fh_type *fh_type) 389 enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
354 { 390 {
355 switch (op) { 391 switch (op) {
356 case ELS_ADISC: 392 case ELS_ADISC:
357 fc_adisc_fill(lport, fp); 393 fc_adisc_fill(lport, fp);
358 break; 394 break;
359 395
360 case ELS_PLOGI: 396 case ELS_PLOGI:
361 fc_plogi_fill(lport, fp, ELS_PLOGI); 397 fc_plogi_fill(lport, fp, ELS_PLOGI);
362 break; 398 break;
363 399
364 case ELS_FLOGI: 400 case ELS_FLOGI:
365 fc_flogi_fill(lport, fp); 401 fc_flogi_fill(lport, fp);
366 break; 402 break;
367 403
368 case ELS_FDISC: 404 case ELS_FDISC:
369 fc_fdisc_fill(lport, fp); 405 fc_fdisc_fill(lport, fp);
370 break; 406 break;
371 407
372 case ELS_LOGO: 408 case ELS_LOGO:
373 fc_logo_fill(lport, fp); 409 fc_logo_fill(lport, fp);
374 break; 410 break;
375 411
376 case ELS_RTV: 412 case ELS_RTV:
377 fc_rtv_fill(lport, fp); 413 fc_rtv_fill(lport, fp);
378 break; 414 break;
379 415
380 case ELS_REC: 416 case ELS_REC:
381 fc_rec_fill(lport, fp); 417 fc_rec_fill(lport, fp);
382 break; 418 break;
383 419
384 case ELS_PRLI: 420 case ELS_PRLI:
385 fc_prli_fill(lport, fp); 421 fc_prli_fill(lport, fp);
386 break; 422 break;
387 423
388 case ELS_SCR: 424 case ELS_SCR:
389 fc_scr_fill(lport, fp); 425 fc_scr_fill(lport, fp);
390 break; 426 break;
391 427
392 default: 428 default:
393 return -EINVAL; 429 return -EINVAL;
394 } 430 }
395 431
396 *r_ctl = FC_RCTL_ELS_REQ; 432 *r_ctl = FC_RCTL_ELS_REQ;
397 *fh_type = FC_TYPE_ELS; 433 *fh_type = FC_TYPE_ELS;
398 return 0; 434 return 0;
399 } 435 }
400 #endif /* _FC_ENCODE_H_ */ 436 #endif /* _FC_ENCODE_H_ */
401 437