diff options
-rw-r--r-- | drivers/scsi/libfc/fc_elsct.c | 3 | ||||
-rw-r--r-- | include/scsi/fc_encode.h | 60 |
2 files changed, 49 insertions, 14 deletions
diff --git a/drivers/scsi/libfc/fc_elsct.c b/drivers/scsi/libfc/fc_elsct.c index e17a28d324d0..c2384d501470 100644 --- a/drivers/scsi/libfc/fc_elsct.c +++ b/drivers/scsi/libfc/fc_elsct.c | |||
@@ -56,8 +56,7 @@ struct fc_seq *fc_elsct_send(struct fc_lport *lport, u32 did, | |||
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) { |
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, |