diff options
author | Neerav Parikh <neerav.parikh@intel.com> | 2012-01-22 20:30:00 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 09:08:58 -0500 |
commit | 1ea2c1daf4476ac798b1de8196f11dd36425b5ae (patch) | |
tree | de1d14fa0c5b912e22947b0e2177c0ee31b9ba4e /include/scsi | |
parent | a9277e7783651d4e0a849f7988340b1c1cf748a4 (diff) |
[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>
Diffstat (limited to 'include/scsi')
-rw-r--r-- | include/scsi/fc_encode.h | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index be418d8448a5..73bc43329f86 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h | |||
@@ -97,7 +97,9 @@ static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp) | |||
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; |
@@ -106,14 +108,14 @@ static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, | |||
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. |
@@ -121,7 +123,7 @@ static inline struct fc_ct_req *fc_ct_hdr_fill(const struct fc_frame *fp, | |||
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) |
@@ -131,23 +133,28 @@ static inline int fc_ct_fill(struct fc_lport *lport, | |||
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) |
@@ -157,14 +164,16 @@ static inline int fc_ct_fill(struct fc_lport *lport, | |||
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); |
@@ -173,7 +182,8 @@ static inline int fc_ct_fill(struct fc_lport *lport, | |||
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); |
@@ -189,6 +199,32 @@ static inline int fc_ct_fill(struct fc_lport *lport, | |||
189 | } | 199 | } |
190 | 200 | ||
191 | /** | 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 | } | ||
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, |