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 <linux/unaligned.h>
11 #include <linux/utsname.h>
12 #include <scsi/fc/fc_ms.h>
15 * F_CTL values for simple requests and responses.
17 #define FC_FCTL_REQ (FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT)
18 #define FC_FCTL_RESP (FC_FC_EX_CTX | FC_FC_LAST_SEQ | \
19 FC_FC_END_SEQ | FC_FC_SEQ_INIT)
22 struct fc_ns_fid fid
; /* port ID object */
23 struct fc_ns_fts fts
; /* FC4-types object */
29 struct fc_ns_gid_ft gid
;
30 struct fc_ns_rn_id rn
;
32 struct fc_ns_rff_id rff
;
34 struct fc_ns_rsnn snn
;
35 struct fc_ns_rspn spn
;
36 struct fc_fdmi_rhba rhba
;
37 struct fc_fdmi_rpa rpa
;
38 struct fc_fdmi_dprt dprt
;
39 struct fc_fdmi_dhba dhba
;
44 * fc_adisc_fill() - Fill in adisc request frame
46 * @fp: fc frame where payload will be placed.
48 static inline void fc_adisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
50 struct fc_els_adisc
*adisc
;
52 adisc
= fc_frame_payload_get(fp
, sizeof(*adisc
));
53 memset(adisc
, 0, sizeof(*adisc
));
54 adisc
->adisc_cmd
= ELS_ADISC
;
55 put_unaligned_be64(lport
->wwpn
, &adisc
->adisc_wwpn
);
56 put_unaligned_be64(lport
->wwnn
, &adisc
->adisc_wwnn
);
57 hton24(adisc
->adisc_port_id
, lport
->port_id
);
61 * fc_ct_hdr_fill- fills ct header and reset ct payload
62 * returns pointer to ct request.
64 static inline struct fc_ct_req
*fc_ct_hdr_fill(const struct fc_frame
*fp
,
65 unsigned int op
, size_t req_size
,
66 enum fc_ct_fs_type fs_type
,
72 ct_plen
= sizeof(struct fc_ct_hdr
) + req_size
;
73 ct
= fc_frame_payload_get(fp
, ct_plen
);
74 memset(ct
, 0, ct_plen
);
75 ct
->hdr
.ct_rev
= FC_CT_REV
;
76 ct
->hdr
.ct_fs_type
= fs_type
;
77 ct
->hdr
.ct_fs_subtype
= subtype
;
78 ct
->hdr
.ct_cmd
= htons((u16
) op
);
83 * fc_ct_ns_fill() - Fill in a name service request frame
85 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
86 * @fp: frame to contain payload.
88 * @r_ctl: pointer to FC header R_CTL.
89 * @fh_type: pointer to FC-4 type.
91 static inline int fc_ct_ns_fill(struct fc_lport
*lport
,
92 u32 fc_id
, struct fc_frame
*fp
,
93 unsigned int op
, enum fc_rctl
*r_ctl
,
94 enum fc_fh_type
*fh_type
)
101 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_gid_ft
),
102 FC_FST_DIR
, FC_NS_SUBTYPE
);
103 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
107 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_fid
),
108 FC_FST_DIR
, FC_NS_SUBTYPE
);
109 ct
->payload
.gid
.fn_fc4_type
= FC_TYPE_FCP
;
110 hton24(ct
->payload
.fid
.fp_fid
, fc_id
);
114 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rft
),
115 FC_FST_DIR
, FC_NS_SUBTYPE
);
116 hton24(ct
->payload
.rft
.fid
.fp_fid
, lport
->port_id
);
117 ct
->payload
.rft
.fts
= lport
->fcts
;
121 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rff_id
),
122 FC_FST_DIR
, FC_NS_SUBTYPE
);
123 hton24(ct
->payload
.rff
.fr_fid
.fp_fid
, lport
->port_id
);
124 ct
->payload
.rff
.fr_type
= FC_TYPE_FCP
;
125 if (lport
->service_params
& FCP_SPPF_INIT_FCN
)
126 ct
->payload
.rff
.fr_feat
= FCP_FEAT_INIT
;
127 if (lport
->service_params
& FCP_SPPF_TARG_FCN
)
128 ct
->payload
.rff
.fr_feat
|= FCP_FEAT_TARG
;
132 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rn_id
),
133 FC_FST_DIR
, FC_NS_SUBTYPE
);
134 hton24(ct
->payload
.rn
.fr_fid
.fp_fid
, lport
->port_id
);
135 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.rn
.fr_wwn
);
139 len
= strnlen(fc_host_symbolic_name(lport
->host
),
140 FC_SYMBOLIC_NAME_SIZE
);
141 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rspn
) + len
,
142 FC_FST_DIR
, FC_NS_SUBTYPE
);
143 hton24(ct
->payload
.spn
.fr_fid
.fp_fid
, lport
->port_id
);
144 memcpy(ct
->payload
.spn
.fr_name
,
145 fc_host_symbolic_name(lport
->host
), len
);
146 ct
->payload
.spn
.fr_name_len
= len
;
150 len
= strnlen(fc_host_symbolic_name(lport
->host
),
151 FC_SYMBOLIC_NAME_SIZE
);
152 ct
= fc_ct_hdr_fill(fp
, op
, sizeof(struct fc_ns_rsnn
) + len
,
153 FC_FST_DIR
, FC_NS_SUBTYPE
);
154 put_unaligned_be64(lport
->wwnn
, &ct
->payload
.snn
.fr_wwn
);
155 memcpy(ct
->payload
.snn
.fr_name
,
156 fc_host_symbolic_name(lport
->host
), len
);
157 ct
->payload
.snn
.fr_name_len
= len
;
163 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
164 *fh_type
= FC_TYPE_CT
;
168 static inline void fc_ct_ms_fill_attr(struct fc_fdmi_attr_entry
*entry
,
169 const char *in
, size_t len
)
173 copied
= strscpy(entry
->value
, in
, len
);
174 if (copied
> 0 && copied
+ 1 < len
)
175 memset(entry
->value
+ copied
+ 1, 0, len
- copied
- 1);
179 * fc_ct_ms_fill() - Fill in a mgmt service request frame
180 * @lport: local port.
181 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
182 * @fp: frame to contain payload.
184 * @r_ctl: pointer to FC header R_CTL.
185 * @fh_type: pointer to FC-4 type.
187 static inline int fc_ct_ms_fill(struct fc_lport
*lport
,
188 u32 fc_id
, struct fc_frame
*fp
,
189 unsigned int op
, enum fc_rctl
*r_ctl
,
190 enum fc_fh_type
*fh_type
)
192 struct fc_ct_req
*ct
;
194 struct fc_fdmi_attr_entry
*entry
;
195 struct fs_fdmi_attrs
*hba_attrs
;
197 struct fc_host_attrs
*fc_host
= shost_to_fc_host(lport
->host
);
202 len
= sizeof(struct fc_fdmi_rhba
);
203 len
-= sizeof(struct fc_fdmi_attr_entry
);
204 len
+= (numattrs
* FC_FDMI_ATTR_ENTRY_HEADER_LEN
);
205 len
+= FC_FDMI_HBA_ATTR_NODENAME_LEN
;
206 len
+= FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
;
207 len
+= FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
;
208 len
+= FC_FDMI_HBA_ATTR_MODEL_LEN
;
209 len
+= FC_FDMI_HBA_ATTR_MODELDESCR_LEN
;
210 len
+= FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
;
211 len
+= FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
;
212 len
+= FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
;
213 len
+= FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
;
214 len
+= FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
;
215 len
+= FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN
;
217 if (fc_host
->fdmi_version
== FDMI_V2
) {
219 len
+= FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN
;
220 len
+= FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN
;
221 len
+= FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN
;
222 len
+= FC_FDMI_HBA_ATTR_FABRICNAME_LEN
;
223 len
+= FC_FDMI_HBA_ATTR_BIOSVERSION_LEN
;
224 len
+= FC_FDMI_HBA_ATTR_BIOSSTATE_LEN
;
225 len
+= FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN
;
228 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
232 put_unaligned_be64(lport
->wwpn
, &ct
->payload
.rhba
.hbaid
.id
);
233 /* Number of Ports - always 1 */
234 put_unaligned_be32(1, &ct
->payload
.rhba
.port
.numport
);
236 put_unaligned_be64(lport
->wwpn
,
237 &ct
->payload
.rhba
.port
.port
[0].portname
);
240 put_unaligned_be32(numattrs
,
241 &ct
->payload
.rhba
.hba_attrs
.numattrs
);
242 hba_attrs
= &ct
->payload
.rhba
.hba_attrs
;
243 entry
= (struct fc_fdmi_attr_entry
*)hba_attrs
->attr
;
245 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
246 len
+= FC_FDMI_HBA_ATTR_NODENAME_LEN
;
247 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODENAME
,
249 put_unaligned_be16(len
, &entry
->len
);
250 put_unaligned_be64(lport
->wwnn
,
251 (__be64
*)&entry
->value
);
254 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
255 FC_FDMI_HBA_ATTR_NODENAME_LEN
);
256 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
257 len
+= FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
;
258 put_unaligned_be16(FC_FDMI_HBA_ATTR_MANUFACTURER
,
260 put_unaligned_be16(len
, &entry
->len
);
261 fc_ct_ms_fill_attr(entry
,
262 fc_host_manufacturer(lport
->host
),
263 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
);
266 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
267 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN
);
268 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
269 len
+= FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
;
270 put_unaligned_be16(FC_FDMI_HBA_ATTR_SERIALNUMBER
,
272 put_unaligned_be16(len
, &entry
->len
);
273 fc_ct_ms_fill_attr(entry
,
274 fc_host_serial_number(lport
->host
),
275 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
);
278 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
279 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN
);
280 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
281 len
+= FC_FDMI_HBA_ATTR_MODEL_LEN
;
282 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODEL
,
284 put_unaligned_be16(len
, &entry
->len
);
285 fc_ct_ms_fill_attr(entry
,
286 fc_host_model(lport
->host
),
287 FC_FDMI_HBA_ATTR_MODEL_LEN
);
289 /* Model Description */
290 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
291 FC_FDMI_HBA_ATTR_MODEL_LEN
);
292 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
293 len
+= FC_FDMI_HBA_ATTR_MODELDESCR_LEN
;
294 put_unaligned_be16(FC_FDMI_HBA_ATTR_MODELDESCRIPTION
,
296 put_unaligned_be16(len
, &entry
->len
);
297 fc_ct_ms_fill_attr(entry
,
298 fc_host_model_description(lport
->host
),
299 FC_FDMI_HBA_ATTR_MODELDESCR_LEN
);
301 /* Hardware Version */
302 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
303 FC_FDMI_HBA_ATTR_MODELDESCR_LEN
);
304 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
305 len
+= FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
;
306 put_unaligned_be16(FC_FDMI_HBA_ATTR_HARDWAREVERSION
,
308 put_unaligned_be16(len
, &entry
->len
);
309 fc_ct_ms_fill_attr(entry
,
310 fc_host_hardware_version(lport
->host
),
311 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
);
314 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
315 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN
);
316 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
317 len
+= FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
;
318 put_unaligned_be16(FC_FDMI_HBA_ATTR_DRIVERVERSION
,
320 put_unaligned_be16(len
, &entry
->len
);
321 fc_ct_ms_fill_attr(entry
,
322 fc_host_driver_version(lport
->host
),
323 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
);
325 /* OptionROM Version */
326 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
327 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN
);
328 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
329 len
+= FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
;
330 put_unaligned_be16(FC_FDMI_HBA_ATTR_OPTIONROMVERSION
,
332 put_unaligned_be16(len
, &entry
->len
);
333 fc_ct_ms_fill_attr(entry
,
335 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
);
337 /* Firmware Version */
338 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
339 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN
);
340 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
341 len
+= FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
;
342 put_unaligned_be16(FC_FDMI_HBA_ATTR_FIRMWAREVERSION
,
344 put_unaligned_be16(len
, &entry
->len
);
345 fc_ct_ms_fill_attr(entry
,
346 fc_host_firmware_version(lport
->host
),
347 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
);
349 /* OS Name and Version */
350 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
351 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN
);
352 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
353 len
+= FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
;
354 put_unaligned_be16(FC_FDMI_HBA_ATTR_OSNAMEVERSION
,
356 put_unaligned_be16(len
, &entry
->len
);
357 snprintf((char *)&entry
->value
,
358 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
,
360 init_utsname()->sysname
,
361 init_utsname()->release
);
364 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
365 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN
);
366 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
367 len
+= FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN
;
368 put_unaligned_be16(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD
,
370 put_unaligned_be16(len
, &entry
->len
);
371 put_unaligned_be32(fc_host_max_ct_payload(lport
->host
),
374 if (fc_host
->fdmi_version
== FDMI_V2
) {
375 /* Node symbolic name */
376 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
377 FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN
);
378 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
379 len
+= FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN
;
380 put_unaligned_be16(FC_FDMI_HBA_ATTR_NODESYMBLNAME
,
382 put_unaligned_be16(len
, &entry
->len
);
383 fc_ct_ms_fill_attr(entry
,
384 fc_host_symbolic_name(lport
->host
),
385 FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN
);
387 /* Vendor specific info */
388 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
389 FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN
);
390 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
391 len
+= FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN
;
392 put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO
,
394 put_unaligned_be16(len
, &entry
->len
);
395 put_unaligned_be32(0,
398 /* Number of ports */
399 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
400 FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO_LEN
);
401 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
402 len
+= FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN
;
403 put_unaligned_be16(FC_FDMI_HBA_ATTR_NUMBEROFPORTS
,
405 put_unaligned_be16(len
, &entry
->len
);
406 put_unaligned_be32(fc_host_num_ports(lport
->host
),
410 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
411 FC_FDMI_HBA_ATTR_NUMBEROFPORTS_LEN
);
412 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
413 len
+= FC_FDMI_HBA_ATTR_FABRICNAME_LEN
;
414 put_unaligned_be16(FC_FDMI_HBA_ATTR_FABRICNAME
,
416 put_unaligned_be16(len
, &entry
->len
);
417 put_unaligned_be64(fc_host_fabric_name(lport
->host
),
421 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
422 FC_FDMI_HBA_ATTR_FABRICNAME_LEN
);
423 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
424 len
+= FC_FDMI_HBA_ATTR_BIOSVERSION_LEN
;
425 put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSVERSION
,
427 put_unaligned_be16(len
, &entry
->len
);
428 fc_ct_ms_fill_attr(entry
,
429 fc_host_bootbios_version(lport
->host
),
430 FC_FDMI_HBA_ATTR_BIOSVERSION_LEN
);
433 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
434 FC_FDMI_HBA_ATTR_BIOSVERSION_LEN
);
435 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
436 len
+= FC_FDMI_HBA_ATTR_BIOSSTATE_LEN
;
437 put_unaligned_be16(FC_FDMI_HBA_ATTR_BIOSSTATE
,
439 put_unaligned_be16(len
, &entry
->len
);
440 put_unaligned_be32(fc_host_bootbios_state(lport
->host
),
443 /* Vendor identifier */
444 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
445 FC_FDMI_HBA_ATTR_BIOSSTATE_LEN
);
446 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
447 len
+= FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN
;
448 put_unaligned_be16(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER
,
450 put_unaligned_be16(len
, &entry
->len
);
451 fc_ct_ms_fill_attr(entry
,
452 fc_host_vendor_identifier(lport
->host
),
453 FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN
);
459 len
= sizeof(struct fc_fdmi_rpa
);
460 len
-= sizeof(struct fc_fdmi_attr_entry
);
461 len
+= (numattrs
* FC_FDMI_ATTR_ENTRY_HEADER_LEN
);
462 len
+= FC_FDMI_PORT_ATTR_FC4TYPES_LEN
;
463 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
;
464 len
+= FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
;
465 len
+= FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
;
466 len
+= FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
;
467 len
+= FC_FDMI_PORT_ATTR_HOSTNAME_LEN
;
470 if (fc_host
->fdmi_version
== FDMI_V2
) {
473 len
+= FC_FDMI_PORT_ATTR_NODENAME_LEN
;
474 len
+= FC_FDMI_PORT_ATTR_PORTNAME_LEN
;
475 len
+= FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN
;
476 len
+= FC_FDMI_PORT_ATTR_PORTTYPE_LEN
;
477 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN
;
478 len
+= FC_FDMI_PORT_ATTR_FABRICNAME_LEN
;
479 len
+= FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN
;
480 len
+= FC_FDMI_PORT_ATTR_PORTSTATE_LEN
;
481 len
+= FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN
;
482 len
+= FC_FDMI_PORT_ATTR_PORTID_LEN
;
486 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
490 put_unaligned_be64(lport
->wwpn
,
491 &ct
->payload
.rpa
.port
.portname
);
493 /* Port Attributes */
494 put_unaligned_be32(numattrs
,
495 &ct
->payload
.rpa
.hba_attrs
.numattrs
);
497 hba_attrs
= &ct
->payload
.rpa
.hba_attrs
;
498 entry
= (struct fc_fdmi_attr_entry
*)hba_attrs
->attr
;
501 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
502 len
+= FC_FDMI_PORT_ATTR_FC4TYPES_LEN
;
503 put_unaligned_be16(FC_FDMI_PORT_ATTR_FC4TYPES
,
505 put_unaligned_be16(len
, &entry
->len
);
506 memcpy(&entry
->value
, fc_host_supported_fc4s(lport
->host
),
507 FC_FDMI_PORT_ATTR_FC4TYPES_LEN
);
509 /* Supported Speed */
510 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
511 FC_FDMI_PORT_ATTR_FC4TYPES_LEN
);
512 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
513 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
;
514 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED
,
516 put_unaligned_be16(len
, &entry
->len
);
518 put_unaligned_be32(fc_host_supported_speeds(lport
->host
),
521 /* Current Port Speed */
522 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
523 FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN
);
524 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
525 len
+= FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
;
526 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED
,
528 put_unaligned_be16(len
, &entry
->len
);
529 put_unaligned_be32(lport
->link_speed
,
533 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
534 FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN
);
535 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
536 len
+= FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
;
537 put_unaligned_be16(FC_FDMI_PORT_ATTR_MAXFRAMESIZE
,
539 put_unaligned_be16(len
, &entry
->len
);
540 put_unaligned_be32(fc_host_maxframe_size(lport
->host
),
544 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
545 FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN
);
546 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
547 len
+= FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
;
548 put_unaligned_be16(FC_FDMI_PORT_ATTR_OSDEVICENAME
,
550 put_unaligned_be16(len
, &entry
->len
);
551 /* Use the sysfs device name */
552 fc_ct_ms_fill_attr(entry
,
553 dev_name(&lport
->host
->shost_gendev
),
554 strnlen(dev_name(&lport
->host
->shost_gendev
),
555 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
));
558 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
559 FC_FDMI_PORT_ATTR_OSDEVICENAME_LEN
);
560 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
561 len
+= FC_FDMI_PORT_ATTR_HOSTNAME_LEN
;
562 put_unaligned_be16(FC_FDMI_PORT_ATTR_HOSTNAME
,
564 put_unaligned_be16(len
, &entry
->len
);
565 if (strlen(fc_host_system_hostname(lport
->host
)))
566 fc_ct_ms_fill_attr(entry
,
567 fc_host_system_hostname(lport
->host
),
568 strnlen(fc_host_system_hostname(lport
->host
),
569 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
));
571 fc_ct_ms_fill_attr(entry
,
572 init_utsname()->nodename
,
573 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
);
576 if (fc_host
->fdmi_version
== FDMI_V2
) {
579 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
580 FC_FDMI_PORT_ATTR_HOSTNAME_LEN
);
581 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
582 len
+= FC_FDMI_PORT_ATTR_NODENAME_LEN
;
583 put_unaligned_be16(FC_FDMI_PORT_ATTR_NODENAME
,
585 put_unaligned_be16(len
, &entry
->len
);
586 put_unaligned_be64(fc_host_node_name(lport
->host
),
590 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
591 FC_FDMI_PORT_ATTR_NODENAME_LEN
);
592 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
593 len
+= FC_FDMI_PORT_ATTR_PORTNAME_LEN
;
594 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTNAME
,
596 put_unaligned_be16(len
, &entry
->len
);
597 put_unaligned_be64(lport
->wwpn
,
600 /* Port symbolic name */
601 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
602 FC_FDMI_PORT_ATTR_PORTNAME_LEN
);
603 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
604 len
+= FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN
;
605 put_unaligned_be16(FC_FDMI_PORT_ATTR_SYMBOLICNAME
,
607 put_unaligned_be16(len
, &entry
->len
);
608 fc_ct_ms_fill_attr(entry
,
609 fc_host_symbolic_name(lport
->host
),
610 FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN
);
613 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
614 FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN
);
615 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
616 len
+= FC_FDMI_PORT_ATTR_PORTTYPE_LEN
;
617 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTTYPE
,
619 put_unaligned_be16(len
, &entry
->len
);
620 put_unaligned_be32(fc_host_port_type(lport
->host
),
623 /* Supported class of service */
624 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
625 FC_FDMI_PORT_ATTR_PORTTYPE_LEN
);
626 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
627 len
+= FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN
;
628 put_unaligned_be16(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC
,
630 put_unaligned_be16(len
, &entry
->len
);
631 put_unaligned_be32(fc_host_supported_classes(lport
->host
),
634 /* Port Fabric name */
635 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
636 FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC_LEN
);
637 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
638 len
+= FC_FDMI_PORT_ATTR_FABRICNAME_LEN
;
639 put_unaligned_be16(FC_FDMI_PORT_ATTR_FABRICNAME
,
641 put_unaligned_be16(len
, &entry
->len
);
642 put_unaligned_be64(fc_host_fabric_name(lport
->host
),
645 /* Port active FC-4 */
646 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
647 FC_FDMI_PORT_ATTR_FABRICNAME_LEN
);
648 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
649 len
+= FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN
;
650 put_unaligned_be16(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE
,
652 put_unaligned_be16(len
, &entry
->len
);
653 memcpy(&entry
->value
, fc_host_active_fc4s(lport
->host
),
654 FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN
);
657 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
658 FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN
);
659 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
660 len
+= FC_FDMI_PORT_ATTR_PORTSTATE_LEN
;
661 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTSTATE
,
663 put_unaligned_be16(len
, &entry
->len
);
664 put_unaligned_be32(fc_host_port_state(lport
->host
),
667 /* Discovered ports */
668 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
669 FC_FDMI_PORT_ATTR_PORTSTATE_LEN
);
670 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
671 len
+= FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN
;
672 put_unaligned_be16(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS
,
674 put_unaligned_be16(len
, &entry
->len
);
675 put_unaligned_be32(fc_host_num_discovered_ports(lport
->host
),
679 entry
= (struct fc_fdmi_attr_entry
*)((char *)entry
->value
+
680 FC_FDMI_PORT_ATTR_DISCOVEREDPORTS_LEN
);
681 len
= FC_FDMI_ATTR_ENTRY_HEADER_LEN
;
682 len
+= FC_FDMI_PORT_ATTR_PORTID_LEN
;
683 put_unaligned_be16(FC_FDMI_PORT_ATTR_PORTID
,
685 put_unaligned_be16(len
, &entry
->len
);
686 put_unaligned_be32(fc_host_port_id(lport
->host
),
692 len
= sizeof(struct fc_fdmi_dprt
);
693 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
696 put_unaligned_be64(lport
->wwpn
,
697 &ct
->payload
.dprt
.port
.portname
);
700 len
= sizeof(struct fc_fdmi_dhba
);
701 ct
= fc_ct_hdr_fill(fp
, op
, len
, FC_FST_MGMT
,
704 put_unaligned_be64(lport
->wwpn
, &ct
->payload
.dhba
.hbaid
.id
);
709 *r_ctl
= FC_RCTL_DD_UNSOL_CTL
;
710 *fh_type
= FC_TYPE_CT
;
715 * fc_ct_fill() - Fill in a common transport service request frame
716 * @lport: local port.
717 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
718 * @fp: frame to contain payload.
720 * @r_ctl: pointer to FC header R_CTL.
721 * @fh_type: pointer to FC-4 type.
723 static inline int fc_ct_fill(struct fc_lport
*lport
,
724 u32 fc_id
, struct fc_frame
*fp
,
725 unsigned int op
, enum fc_rctl
*r_ctl
,
726 enum fc_fh_type
*fh_type
, u32
*did
)
731 case FC_FID_MGMT_SERV
:
732 rc
= fc_ct_ms_fill(lport
, fc_id
, fp
, op
, r_ctl
, fh_type
);
733 *did
= FC_FID_MGMT_SERV
;
735 case FC_FID_DIR_SERV
:
737 rc
= fc_ct_ns_fill(lport
, fc_id
, fp
, op
, r_ctl
, fh_type
);
738 *did
= FC_FID_DIR_SERV
;
745 * fc_plogi_fill - Fill in plogi request frame
747 static inline void fc_plogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
,
750 struct fc_els_flogi
*plogi
;
751 struct fc_els_csp
*csp
;
752 struct fc_els_cssp
*cp
;
754 plogi
= fc_frame_payload_get(fp
, sizeof(*plogi
));
755 memset(plogi
, 0, sizeof(*plogi
));
756 plogi
->fl_cmd
= (u8
) op
;
757 put_unaligned_be64(lport
->wwpn
, &plogi
->fl_wwpn
);
758 put_unaligned_be64(lport
->wwnn
, &plogi
->fl_wwnn
);
760 csp
= &plogi
->fl_csp
;
761 csp
->sp_hi_ver
= 0x20;
762 csp
->sp_lo_ver
= 0x20;
763 csp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
764 csp
->sp_bb_data
= htons((u16
) lport
->mfs
);
765 cp
= &plogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
766 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
767 csp
->sp_features
= htons(FC_SP_FT_CIRO
);
768 csp
->sp_tot_seq
= htons(255); /* seq. we accept */
769 csp
->sp_rel_off
= htons(0x1f);
770 csp
->sp_e_d_tov
= htonl(lport
->e_d_tov
);
772 cp
->cp_rdfs
= htons((u16
) lport
->mfs
);
773 cp
->cp_con_seq
= htons(255);
778 * fc_flogi_fill - Fill in a flogi request frame.
780 static inline void fc_flogi_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
782 struct fc_els_csp
*sp
;
783 struct fc_els_cssp
*cp
;
784 struct fc_els_flogi
*flogi
;
786 flogi
= fc_frame_payload_get(fp
, sizeof(*flogi
));
787 memset(flogi
, 0, sizeof(*flogi
));
788 flogi
->fl_cmd
= (u8
) ELS_FLOGI
;
789 put_unaligned_be64(lport
->wwpn
, &flogi
->fl_wwpn
);
790 put_unaligned_be64(lport
->wwnn
, &flogi
->fl_wwnn
);
792 sp
->sp_hi_ver
= 0x20;
793 sp
->sp_lo_ver
= 0x20;
794 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
795 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
796 cp
= &flogi
->fl_cssp
[3 - 1]; /* class 3 parameters */
797 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
798 if (lport
->does_npiv
)
799 sp
->sp_features
= htons(FC_SP_FT_NPIV
);
803 * fc_fdisc_fill - Fill in a fdisc request frame.
805 static inline void fc_fdisc_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
807 struct fc_els_csp
*sp
;
808 struct fc_els_cssp
*cp
;
809 struct fc_els_flogi
*fdisc
;
811 fdisc
= fc_frame_payload_get(fp
, sizeof(*fdisc
));
812 memset(fdisc
, 0, sizeof(*fdisc
));
813 fdisc
->fl_cmd
= (u8
) ELS_FDISC
;
814 put_unaligned_be64(lport
->wwpn
, &fdisc
->fl_wwpn
);
815 put_unaligned_be64(lport
->wwnn
, &fdisc
->fl_wwnn
);
817 sp
->sp_hi_ver
= 0x20;
818 sp
->sp_lo_ver
= 0x20;
819 sp
->sp_bb_cred
= htons(10); /* this gets set by gateway */
820 sp
->sp_bb_data
= htons((u16
) lport
->mfs
);
821 cp
= &fdisc
->fl_cssp
[3 - 1]; /* class 3 parameters */
822 cp
->cp_class
= htons(FC_CPC_VALID
| FC_CPC_SEQ
);
826 * fc_logo_fill - Fill in a logo request frame.
828 static inline void fc_logo_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
830 struct fc_els_logo
*logo
;
832 logo
= fc_frame_payload_get(fp
, sizeof(*logo
));
833 memset(logo
, 0, sizeof(*logo
));
834 logo
->fl_cmd
= ELS_LOGO
;
835 hton24(logo
->fl_n_port_id
, lport
->port_id
);
836 logo
->fl_n_port_wwn
= htonll(lport
->wwpn
);
840 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
842 static inline void fc_rtv_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
844 struct fc_els_rtv
*rtv
;
846 rtv
= fc_frame_payload_get(fp
, sizeof(*rtv
));
847 memset(rtv
, 0, sizeof(*rtv
));
848 rtv
->rtv_cmd
= ELS_RTV
;
852 * fc_rec_fill - Fill in rec request frame
854 static inline void fc_rec_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
856 struct fc_els_rec
*rec
;
857 struct fc_exch
*ep
= fc_seq_exch(fr_seq(fp
));
859 rec
= fc_frame_payload_get(fp
, sizeof(*rec
));
860 memset(rec
, 0, sizeof(*rec
));
861 rec
->rec_cmd
= ELS_REC
;
862 hton24(rec
->rec_s_id
, lport
->port_id
);
863 rec
->rec_ox_id
= htons(ep
->oxid
);
864 rec
->rec_rx_id
= htons(ep
->rxid
);
868 * fc_prli_fill - Fill in prli request frame
870 static inline void fc_prli_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
873 struct fc_els_prli prli
;
874 struct fc_els_spp spp
;
877 pp
= fc_frame_payload_get(fp
, sizeof(*pp
));
878 memset(pp
, 0, sizeof(*pp
));
879 pp
->prli
.prli_cmd
= ELS_PRLI
;
880 pp
->prli
.prli_spp_len
= sizeof(struct fc_els_spp
);
881 pp
->prli
.prli_len
= htons(sizeof(*pp
));
882 pp
->spp
.spp_type
= FC_TYPE_FCP
;
883 pp
->spp
.spp_flags
= FC_SPP_EST_IMG_PAIR
;
884 pp
->spp
.spp_params
= htonl(lport
->service_params
);
888 * fc_scr_fill - Fill in a scr request frame.
890 static inline void fc_scr_fill(struct fc_lport
*lport
, struct fc_frame
*fp
)
892 struct fc_els_scr
*scr
;
894 scr
= fc_frame_payload_get(fp
, sizeof(*scr
));
895 memset(scr
, 0, sizeof(*scr
));
896 scr
->scr_cmd
= ELS_SCR
;
897 scr
->scr_reg_func
= ELS_SCRF_FULL
;
901 * fc_els_fill - Fill in an ELS request frame
903 static inline int fc_els_fill(struct fc_lport
*lport
,
905 struct fc_frame
*fp
, unsigned int op
,
906 enum fc_rctl
*r_ctl
, enum fc_fh_type
*fh_type
)
910 fc_adisc_fill(lport
, fp
);
914 fc_plogi_fill(lport
, fp
, ELS_PLOGI
);
918 fc_flogi_fill(lport
, fp
);
922 fc_fdisc_fill(lport
, fp
);
926 fc_logo_fill(lport
, fp
);
930 fc_rtv_fill(lport
, fp
);
934 fc_rec_fill(lport
, fp
);
938 fc_prli_fill(lport
, fp
);
942 fc_scr_fill(lport
, fp
);
949 *r_ctl
= FC_RCTL_ELS_REQ
;
950 *fh_type
= FC_TYPE_ELS
;
953 #endif /* _FC_ENCODE_H_ */