1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright(c) 2008 Intel Corporation. All rights reserved.
5 * Maintained at www.Open-FCoE.org
10 #include <asm/unaligned.h>
11 #include <linux/utsname.h>
14 * F_CTL values for simple requests and responses.
16 #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
17 #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
18 FC_FC_END_SEQ | FC_FC_SEQ_INIT)
21 struct fc_ns_fid fid
; /* port ID object */
22 struct fc_ns_fts fts
; /* FC4-types object */
28 struct fc_ns_gid_ft gid
;
29 struct fc_ns_rn_id rn
;
31 struct fc_ns_rff_id rff
;
33 struct fc_ns_rsnn snn
;
34 struct fc_ns_rspn spn
;
35 struct fc_fdmi_rhba rhba
;
36 struct fc_fdmi_rpa rpa
;
37 struct fc_fdmi_dprt dprt
;
38 struct fc_fdmi_dhba dhba
;
42 static inline void __fc_fill_fc_hdr(struct fc_frame_header
*fh
,
44 u32 did
, u32 sid
, enum fc_fh_type type
,
45 u32 f_ctl
, u32 parm_offset
)
49 hton24(fh
->fh_d_id
, did
);
50 hton24(fh
->fh_s_id
, sid
);
52 hton24(fh
->fh_f_ctl
, f_ctl
);
55 fh
->fh_parm_offset
= htonl(parm_offset
);
59 * fill FC header fields in specified fc_frame
61 static inline void fc_fill_fc_hdr(struct fc_frame
*fp
, enum fc_rctl r_ctl
,
62 u32 did
, u32 sid
, enum fc_fh_type type
,
63 u32 f_ctl
, u32 parm_offset
)
65 struct fc_frame_header
*fh
;
67 fh
= fc_frame_header_get(fp
);
68 __fc_fill_fc_hdr(fh
, r_ctl
, did
, sid
, type
, f_ctl
, parm_offset
);
72 * fc_adisc_fill() - Fill in adisc request frame
74 * @fp: fc frame where payload will be placed.
76 static inline void fc_adisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
78 struct fc_els_adisc
*adisc
;
80 adisc
= fc_frame_payload_get(fp
, sizeof(*adisc
));
81 memset(adisc
, 0, sizeof(*adisc
));
82 adisc
->adisc_cmd
= ELS_ADISC
;
83 put_unaligned_be64(lport
->wwpn
, &adisc
->adisc_wwpn
);
84 put_unaligned_be64(lport
->wwnn
, &adisc
->adisc_wwnn
);
85 hton24(adisc
->adisc_port_id
, lport
->port_id
);
89 * fc_ct_hdr_fill- fills ct header and reset ct payload
90 * returns pointer to ct request.
92 static inline struct fc_ct_req
*fc_ct_hdr_fill(const struct fc_frame
*fp
,
93 unsigned int op
, size_t req_size
,
94 enum fc_ct_fs_type fs_type
,
100 ct_plen
= sizeof(struct fc_ct_hdr
) + req_size
;
101 ct
= fc_frame_payload_get(fp
, ct_plen
);
102 memset(ct
, 0, ct_plen
);
103 ct
->hdr
.ct_rev
= FC_CT_REV
;
104 ct
->hdr
.ct_fs_type
= fs_type
;
105 ct
->hdr
.ct_fs_subtype
= subtype
;
106 ct
->hdr
.ct_cmd
= htons((u16
) op
);
111 * fc_ct_ns_fill() - Fill in a name service request frame
112 * @lport: local port.
113 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
114 * @fp: frame to contain payload.
116 * @r_ctl: pointer to FC header R_CTL.
117 * @fh_type: pointer to FC-4 type.
119 static inline int fc_ct_ns_fill(struct fc_lport
*lport
,
120 u32 fc_id
, struct fc_frame
*fp
,
121 unsigned int op
, enum fc_rctl
*r_ctl
,
122 enum fc_fh_type
*fh_type
)
124 struct fc_ct_req
*ct
;
129 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_gid_ft
),
130 FC_FST_DIR
, FC_NS_SUBTYPE
);
131 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
135 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_fid
),
136 FC_FST_DIR
, FC_NS_SUBTYPE
);
137 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
138 hton24(ct
->payload
.fid
.fp_fid
, fc_id
);
142 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rft
),
143 FC_FST_DIR
, FC_NS_SUBTYPE
);
144 hton24(ct
->payload
.rft
.fid
.fp_fid
, lport
->port_id
);
145 ct
->payload
.rft
.fts
= lport
->fcts
;
149 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rff_id
),
150 FC_FST_DIR
, FC_NS_SUBTYPE
);
151 hton24(ct
->payload
.rff
.fr_fid
.fp_fid
, lport
->port_id
);
152 ct
->payload
.rff
.fr_type
= FC_TYPE_FCP
;
153 if (lport
->service_params
& FCP_SPPF_INIT_FCN
)
154 ct
->payload
.rff
.fr_feat
= FCP_FEAT_INIT
;
155 if (lport
->service_params
& FCP_SPPF_TARG_FCN
)
156 ct
->payload
.rff
.fr_feat
|= FCP_FEAT_TARG
;
160 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rn_id
),
161 FC_FST_DIR
, FC_NS_SUBTYPE
);
162 hton24(ct
->payload
.rn
.fr_fid
.fp_fid
, lport
->port_id
);
163 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.rn
.fr_wwn
);
167 len
= strnlen(fc_host_symbolic_name(lport
->host
), 255);
168 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rspn
) + len
,
169 FC_FST_DIR
, FC_NS_SUBTYPE
);
170 hton24(ct
->payload
.spn
.fr_fid
.fp_fid
, lport
->port_id
);
171 strncpy(ct
->payload
.spn
.fr_name
,
172 fc_host_symbolic_name(lport
->host
), len
);
173 ct
->payload
.spn
.fr_name_len
= len
;
177 len
= strnlen(fc_host_symbolic_name(lport
->host
), 255);
178 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rsnn
) + len
,
179 FC_FST_DIR
, FC_NS_SUBTYPE
);
180 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.snn
.fr_wwn
);
181 strncpy(ct
->payload
.snn
.fr_name
,
182 fc_host_symbolic_name(lport
->host
), len
);
183 ct
->payload
.snn
.fr_name_len
= len
;
189 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
190 *fh_type
= FC_TYPE_CT
;
195 * fc_ct_ms_fill() - Fill in a mgmt service request frame
196 * @lport: local port.
197 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
198 * @fp: frame to contain payload.
200 * @r_ctl: pointer to FC header R_CTL.
201 * @fh_type: pointer to FC-4 type.
203 static inline int fc_ct_ms_fill(struct fc_lport
*lport
,
204 u32 fc_id
, struct fc_frame
*fp
,
205 unsigned int op
, enum fc_rctl
*r_ctl
,
206 enum fc_fh_type
*fh_type
)
208 struct fc_ct_req
*ct
;
210 struct fc_fdmi_attr_entry
*entry
;
211 struct fs_fdmi_attrs
*hba_attrs
;
217 len
= sizeof(struct fc_fdmi_rhba
);
218 len
-= sizeof(struct fc_fdmi_attr_entry
);
219 len
+= (numattrs
* FC_FDMI_ATTR_ENTRY_HEADER_LEN
);
220 len
+= FC_FDMI_HBA_ATTR_NODENAME_LEN
;
221 len
+= FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
;
222 len
+= FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
;
223 len
+= FC_FDMI_HBA_ATTR_MODEL_LEN
;
224 len
+= FC_FDMI_HBA_ATTR_MODELDESCR_LEN
;
225 len
+= FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
;
226 len
+= FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
;
227 len
+= FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
;
228 len
+= FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
;
229 len
+= FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
;
230 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
234 put_unaligned_be64(lport
->wwpn
, &ct
->payload
.rhba
.hbaid
.id
);
235 /* Number of Ports - always 1 */
236 put_unaligned_be32(1, &ct
->payload
.rhba
.port
.numport
);
238 put_unaligned_be64(lport
->wwpn
,
239 &ct
->payload
.rhba
.port
.port
[0].portname
);
242 put_unaligned_be32(numattrs
,
243 &ct
->payload
.rhba
.hba_attrs
.numattrs
);
244 hba_attrs
= &ct
->payload
.rhba
.hba_attrs
;
245 entry
= (struct fc_fdmi_attr_entry
*)hba_attrs
->attr
;
247 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
248 len
+= FC_FDMI_HBA_ATTR_NODENAME_LEN
;
249 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME
,
251 put_unaligned_be16(len
, &entry
->len
);
252 put_unaligned_be64(lport
->wwnn
,
253 (__be64
*)&entry
->value
[0]);
256 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
257 FC_FDMI_HBA_ATTR_NODENAME_LEN
);
258 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
259 len
+= FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
;
260 put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER
,
262 put_unaligned_be16(len
, &entry
->len
);
263 strncpy((char *)&entry
->value
,
264 fc_host_manufacturer(lport
->host
),
265 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
);
268 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
269 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
);
270 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
271 len
+= FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
;
272 put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER
,
274 put_unaligned_be16(len
, &entry
->len
);
275 strncpy((char *)&entry
->value
,
276 fc_host_serial_number(lport
->host
),
277 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
);
280 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
281 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
);
282 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
283 len
+= FC_FDMI_HBA_ATTR_MODEL_LEN
;
284 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL
,
286 put_unaligned_be16(len
, &entry
->len
);
287 strncpy((char *)&entry
->value
,
288 fc_host_model(lport
->host
),
289 FC_FDMI_HBA_ATTR_MODEL_LEN
);
291 /* Model Description */
292 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
293 FC_FDMI_HBA_ATTR_MODEL_LEN
);
294 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
295 len
+= FC_FDMI_HBA_ATTR_MODELDESCR_LEN
;
296 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION
,
298 put_unaligned_be16(len
, &entry
->len
);
299 strncpy((char *)&entry
->value
,
300 fc_host_model_description(lport
->host
),
301 FC_FDMI_HBA_ATTR_MODELDESCR_LEN
);
303 /* Hardware Version */
304 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
305 FC_FDMI_HBA_ATTR_MODELDESCR_LEN
);
306 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
307 len
+= FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
;
308 put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION
,
310 put_unaligned_be16(len
, &entry
->len
);
311 strncpy((char *)&entry
->value
,
312 fc_host_hardware_version(lport
->host
),
313 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
);
316 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
317 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
);
318 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
319 len
+= FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
;
320 put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION
,
322 put_unaligned_be16(len
, &entry
->len
);
323 strncpy((char *)&entry
->value
,
324 fc_host_driver_version(lport
->host
),
325 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
);
327 /* OptionROM Version */
328 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
329 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
);
330 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
331 len
+= FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
;
332 put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION
,
334 put_unaligned_be16(len
, &entry
->len
);
335 strncpy((char *)&entry
->value
,
336 fc_host_optionrom_version(lport
->host
),
337 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
);
339 /* Firmware Version */
340 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
341 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
);
342 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
343 len
+= FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
;
344 put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION
,
346 put_unaligned_be16(len
, &entry
->len
);
347 strncpy((char *)&entry
->value
,
348 fc_host_firmware_version(lport
->host
),
349 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
);
351 /* OS Name and Version */
352 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
353 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
);
354 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
355 len
+= FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
;
356 put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION
,
358 put_unaligned_be16(len
, &entry
->len
);
359 snprintf((char *)&entry
->value
,
360 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
,
362 init_utsname()->sysname
,
363 init_utsname()->release
);
367 len
= sizeof(struct fc_fdmi_rpa
);
368 len
-= sizeof(struct fc_fdmi_attr_entry
);
369 len
+= (numattrs
* FC_FDMI_ATTR_ENTRY_HEADER_LEN
);
370 len
+= FC_FDMI_PORT_ATTR_FC4TYPES_LEN
;
371 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
;
372 len
+= FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
;
373 len
+= FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
;
374 len
+= FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
;
375 len
+= FC_FDMI_PORT_ATTR_HOSTNAME_LEN
;
376 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
380 put_unaligned_be64(lport
->wwpn
,
381 &ct
->payload
.rpa
.port
.portname
);
383 /* Port Attributes */
384 put_unaligned_be32(numattrs
,
385 &ct
->payload
.rpa
.hba_attrs
.numattrs
);
387 hba_attrs
= &ct
->payload
.rpa
.hba_attrs
;
388 entry
= (struct fc_fdmi_attr_entry
*)hba_attrs
->attr
;
391 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
392 len
+= FC_FDMI_PORT_ATTR_FC4TYPES_LEN
;
393 put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES
,
395 put_unaligned_be16(len
, &entry
->len
);
396 memcpy(&entry
->value
, fc_host_supported_fc4s(lport
->host
),
397 FC_FDMI_PORT_ATTR_FC4TYPES_LEN
);
399 /* Supported Speed */
400 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
401 FC_FDMI_PORT_ATTR_FC4TYPES_LEN
);
402 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
403 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
;
404 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED
,
406 put_unaligned_be16(len
, &entry
->len
);
408 put_unaligned_be32(fc_host_supported_speeds(lport
->host
),
411 /* Current Port Speed */
412 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
413 FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
);
414 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
415 len
+= FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
;
416 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED
,
418 put_unaligned_be16(len
, &entry
->len
);
419 put_unaligned_be32(lport
->link_speed
,
423 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
424 FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
);
425 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
426 len
+= FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
;
427 put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE
,
429 put_unaligned_be16(len
, &entry
->len
);
430 put_unaligned_be32(fc_host_maxframe_size(lport
->host
),
434 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
435 FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
);
436 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
437 len
+= FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
;
438 put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME
,
440 put_unaligned_be16(len
, &entry
->len
);
441 /* Use the sysfs device name */
442 strncpy((char *)&entry
->value
,
443 dev_name(&lport
->host
->shost_gendev
),
444 strnlen(dev_name(&lport
->host
->shost_gendev
),
445 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
));
448 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
449 FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
);
450 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
451 len
+= FC_FDMI_PORT_ATTR_HOSTNAME_LEN
;
452 put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME
,
454 put_unaligned_be16(len
, &entry
->len
);
455 if (strlen(fc_host_system_hostname(lport
->host
)))
456 strncpy((char *)&entry
->value
,
457 fc_host_system_hostname(lport
->host
),
458 strnlen(fc_host_system_hostname(lport
->host
),
459 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
));
461 strncpy((char *)&entry
->value
,
462 init_utsname()->nodename
,
463 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
);
466 len
= sizeof(struct fc_fdmi_dprt
);
467 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
470 put_unaligned_be64(lport
->wwpn
,
471 &ct
->payload
.dprt
.port
.portname
);
474 len
= sizeof(struct fc_fdmi_dhba
);
475 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
478 put_unaligned_be64(lport
->wwpn
, &ct
->payload
.dhba
.hbaid
.id
);
483 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
484 *fh_type
= FC_TYPE_CT
;
489 * fc_ct_fill() - Fill in a common transport service request frame
490 * @lport: local port.
491 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
492 * @fp: frame to contain payload.
494 * @r_ctl: pointer to FC header R_CTL.
495 * @fh_type: pointer to FC-4 type.
497 static inline int fc_ct_fill(struct fc_lport
*lport
,
498 u32 fc_id
, struct fc_frame
*fp
,
499 unsigned int op
, enum fc_rctl
*r_ctl
,
500 enum fc_fh_type
*fh_type
, u32
*did
)
505 case FC_FID_MGMT_SERV
:
506 rc
= fc_ct_ms_fill(lport
, fc_id
, fp
, op
, r_ctl
, fh_type
);
507 *did
= FC_FID_MGMT_SERV
;
509 case FC_FID_DIR_SERV
:
511 rc
= fc_ct_ns_fill(lport
, fc_id
, fp
, op
, r_ctl
, fh_type
);
512 *did
= FC_FID_DIR_SERV
;
519 * fc_plogi_fill - Fill in plogi request frame
521 static inline void fc_plogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
,
524 struct fc_els_flogi
*plogi
;
525 struct fc_els_csp
*csp
;
526 struct fc_els_cssp
*cp
;
528 plogi
= fc_frame_payload_get(fp
, sizeof(*plogi
));
529 memset(plogi
, 0, sizeof(*plogi
));
530 plogi
->fl_cmd
= (u8
) op
;
531 put_unaligned_be64(lport
->wwpn
, &plogi
->fl_wwpn
);
532 put_unaligned_be64(lport
->wwnn
, &plogi
->fl_wwnn
);
534 csp
= &plogi
->fl_csp
;
535 csp
->sp_hi_ver
= 0x20;
536 csp
->sp_lo_ver
= 0x20;
537 csp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
538 csp
->sp_bb_data
= htons((u16
) lport
->mfs
);
539 cp
= &plogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
540 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
541 csp
->sp_features
= htons(FC_SP_FT_CIRO
);
542 csp
->sp_tot_seq
= htons(255); /* seq. we accept */
543 csp
->sp_rel_off
= htons(0x1f);
544 csp
->sp_e_d_tov
= htonl(lport
->e_d_tov
);
546 cp
->cp_rdfs
= htons((u16
) lport
->mfs
);
547 cp
->cp_con_seq
= htons(255);
552 * fc_flogi_fill - Fill in a flogi request frame.
554 static inline void fc_flogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
556 struct fc_els_csp
*sp
;
557 struct fc_els_cssp
*cp
;
558 struct fc_els_flogi
*flogi
;
560 flogi
= fc_frame_payload_get(fp
, sizeof(*flogi
));
561 memset(flogi
, 0, sizeof(*flogi
));
562 flogi
->fl_cmd
= (u8
) ELS_FLOGI
;
563 put_unaligned_be64(lport
->wwpn
, &flogi
->fl_wwpn
);
564 put_unaligned_be64(lport
->wwnn
, &flogi
->fl_wwnn
);
566 sp
->sp_hi_ver
= 0x20;
567 sp
->sp_lo_ver
= 0x20;
568 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
569 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
570 cp
= &flogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
571 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
572 if (lport
->does_npiv
)
573 sp
->sp_features
= htons(FC_SP_FT_NPIV
);
577 * fc_fdisc_fill - Fill in a fdisc request frame.
579 static inline void fc_fdisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
581 struct fc_els_csp
*sp
;
582 struct fc_els_cssp
*cp
;
583 struct fc_els_flogi
*fdisc
;
585 fdisc
= fc_frame_payload_get(fp
, sizeof(*fdisc
));
586 memset(fdisc
, 0, sizeof(*fdisc
));
587 fdisc
->fl_cmd
= (u8
) ELS_FDISC
;
588 put_unaligned_be64(lport
->wwpn
, &fdisc
->fl_wwpn
);
589 put_unaligned_be64(lport
->wwnn
, &fdisc
->fl_wwnn
);
591 sp
->sp_hi_ver
= 0x20;
592 sp
->sp_lo_ver
= 0x20;
593 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
594 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
595 cp
= &fdisc
->fl_cssp
[3 - 1]; /* class 3 parameters */
596 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
600 * fc_logo_fill - Fill in a logo request frame.
602 static inline void fc_logo_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
604 struct fc_els_logo
*logo
;
606 logo
= fc_frame_payload_get(fp
, sizeof(*logo
));
607 memset(logo
, 0, sizeof(*logo
));
608 logo
->fl_cmd
= ELS_LOGO
;
609 hton24(logo
->fl_n_port_id
, lport
->port_id
);
610 logo
->fl_n_port_wwn
= htonll(lport
->wwpn
);
614 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
616 static inline void fc_rtv_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
618 struct fc_els_rtv
*rtv
;
620 rtv
= fc_frame_payload_get(fp
, sizeof(*rtv
));
621 memset(rtv
, 0, sizeof(*rtv
));
622 rtv
->rtv_cmd
= ELS_RTV
;
626 * fc_rec_fill - Fill in rec request frame
628 static inline void fc_rec_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
630 struct fc_els_rec
*rec
;
631 struct fc_exch
*ep
= fc_seq_exch(fr_seq(fp
));
633 rec
= fc_frame_payload_get(fp
, sizeof(*rec
));
634 memset(rec
, 0, sizeof(*rec
));
635 rec
->rec_cmd
= ELS_REC
;
636 hton24(rec
->rec_s_id
, lport
->port_id
);
637 rec
->rec_ox_id
= htons(ep
->oxid
);
638 rec
->rec_rx_id
= htons(ep
->rxid
);
642 * fc_prli_fill - Fill in prli request frame
644 static inline void fc_prli_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
647 struct fc_els_prli prli
;
648 struct fc_els_spp spp
;
651 pp
= fc_frame_payload_get(fp
, sizeof(*pp
));
652 memset(pp
, 0, sizeof(*pp
));
653 pp
->prli
.prli_cmd
= ELS_PRLI
;
654 pp
->prli
.prli_spp_len
= sizeof(struct fc_els_spp
);
655 pp
->prli
.prli_len
= htons(sizeof(*pp
));
656 pp
->spp
.spp_type
= FC_TYPE_FCP
;
657 pp
->spp
.spp_flags
= FC_SPP_EST_IMG_PAIR
;
658 pp
->spp
.spp_params
= htonl(lport
->service_params
);
662 * fc_scr_fill - Fill in a scr request frame.
664 static inline void fc_scr_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
666 struct fc_els_scr
*scr
;
668 scr
= fc_frame_payload_get(fp
, sizeof(*scr
));
669 memset(scr
, 0, sizeof(*scr
));
670 scr
->scr_cmd
= ELS_SCR
;
671 scr
->scr_reg_func
= ELS_SCRF_FULL
;
675 * fc_els_fill - Fill in an ELS request frame
677 static inline int fc_els_fill(struct fc_lport
*lport
,
679 struct fc_frame
*fp
, unsigned int op
,
680 enum fc_rctl
*r_ctl
, enum fc_fh_type
*fh_type
)
684 fc_adisc_fill(lport
, fp
);
688 fc_plogi_fill(lport
, fp
, ELS_PLOGI
);
692 fc_flogi_fill(lport
, fp
);
696 fc_fdisc_fill(lport
, fp
);
700 fc_logo_fill(lport
, fp
);
704 fc_rtv_fill(lport
, fp
);
708 fc_rec_fill(lport
, fp
);
712 fc_prli_fill(lport
, fp
);
716 fc_scr_fill(lport
, fp
);
723 *r_ctl
= FC_RCTL_ELS_REQ
;
724 *fh_type
= FC_TYPE_ELS
;
727 #endif /* _FC_ENCODE_H_ */