1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright(c) 2008 Intel Corporation. All rights reserved.
4 *
5 * Maintained at www.Open-FCoE.org
6 */
7
8#ifndef _FC_ENCODE_H_
9#define _FC_ENCODE_H_
10#include <asm/unaligned.h>
11#include <linux/utsname.h>
12#include <scsi/fc/fc_ms.h>
13
14/*
15 * F_CTL values for simple requests and responses.
16 */
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)
20
21struct fc_ns_rft {
22 struct fc_ns_fid fid; /* port ID object */
23 struct fc_ns_fts fts; /* FC4-types object */
24};
25
26struct fc_ct_req {
27 struct fc_ct_hdr hdr;
28 union {
29 struct fc_ns_gid_ft gid;
30 struct fc_ns_rn_id rn;
31 struct fc_ns_rft rft;
32 struct fc_ns_rff_id rff;
33 struct fc_ns_fid fid;
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;
40 } payload;
41};
42
43/**
44 * fc_adisc_fill() - Fill in adisc request frame
45 * @lport: local port.
46 * @fp: fc frame where payload will be placed.
47 */
48static inline void fc_adisc_fill(struct fc_lport *lport, struct fc_frame *fp)
49{
50 struct fc_els_adisc *adisc;
51
52 adisc = fc_frame_payload_get(fp, len: sizeof(*adisc));
53 memset(adisc, 0, sizeof(*adisc));
54 adisc->adisc_cmd = ELS_ADISC;
55 put_unaligned_be64(val: lport->wwpn, p: &adisc->adisc_wwpn);
56 put_unaligned_be64(val: lport->wwnn, p: &adisc->adisc_wwnn);
57 hton24(p: adisc->adisc_port_id, v: lport->port_id);
58}
59
60/**
61 * fc_ct_hdr_fill- fills ct header and reset ct payload
62 * returns pointer to ct request.
63 */
64static 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,
67 u8 subtype)
68{
69 struct fc_ct_req *ct;
70 size_t ct_plen;
71
72 ct_plen = sizeof(struct fc_ct_hdr) + req_size;
73 ct = fc_frame_payload_get(fp, len: 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);
79 return ct;
80}
81
82/**
83 * fc_ct_ns_fill() - Fill in a name service request frame
84 * @lport: local port.
85 * @fc_id: FC_ID of non-destination rport for GPN_ID and similar inquiries.
86 * @fp: frame to contain payload.
87 * @op: CT opcode.
88 * @r_ctl: pointer to FC header R_CTL.
89 * @fh_type: pointer to FC-4 type.
90 */
91static 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)
95{
96 struct fc_ct_req *ct;
97 size_t len;
98
99 switch (op) {
100 case FC_NS_GPN_FT:
101 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_gid_ft),
102 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
103 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
104 break;
105
106 case FC_NS_GPN_ID:
107 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_fid),
108 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
109 ct->payload.gid.fn_fc4_type = FC_TYPE_FCP;
110 hton24(p: ct->payload.fid.fp_fid, v: fc_id);
111 break;
112
113 case FC_NS_RFT_ID:
114 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_rft),
115 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
116 hton24(p: ct->payload.rft.fid.fp_fid, v: lport->port_id);
117 ct->payload.rft.fts = lport->fcts;
118 break;
119
120 case FC_NS_RFF_ID:
121 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_rff_id),
122 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
123 hton24(p: ct->payload.rff.fr_fid.fp_fid, v: 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;
129 break;
130
131 case FC_NS_RNN_ID:
132 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_rn_id),
133 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
134 hton24(p: ct->payload.rn.fr_fid.fp_fid, v: lport->port_id);
135 put_unaligned_be64(val: lport->wwnn, p: &ct->payload.rn.fr_wwn);
136 break;
137
138 case FC_NS_RSPN_ID:
139 len = strnlen(fc_host_symbolic_name(lport->host),
140 FC_SYMBOLIC_NAME_SIZE);
141 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_rspn) + len,
142 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
143 hton24(p: ct->payload.spn.fr_fid.fp_fid, v: 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;
147 break;
148
149 case FC_NS_RSNN_NN:
150 len = strnlen(fc_host_symbolic_name(lport->host),
151 FC_SYMBOLIC_NAME_SIZE);
152 ct = fc_ct_hdr_fill(fp, op, req_size: sizeof(struct fc_ns_rsnn) + len,
153 fs_type: FC_FST_DIR, FC_NS_SUBTYPE);
154 put_unaligned_be64(val: lport->wwnn, p: &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;
158 break;
159
160 default:
161 return -EINVAL;
162 }
163 *r_ctl = FC_RCTL_DD_UNSOL_CTL;
164 *fh_type = FC_TYPE_CT;
165 return 0;
166}
167
168static inline void fc_ct_ms_fill_attr(struct fc_fdmi_attr_entry *entry,
169 const char *in, size_t len)
170{
171 int copied;
172
173 copied = strscpy(entry->value, in, len);
174 if (copied > 0 && copied + 1 < len)
175 memset(entry->value + copied + 1, 0, len - copied - 1);
176}
177
178/**
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.
183 * @op: CT opcode.
184 * @r_ctl: pointer to FC header R_CTL.
185 * @fh_type: pointer to FC-4 type.
186 */
187static 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)
191{
192 struct fc_ct_req *ct;
193 size_t len;
194 struct fc_fdmi_attr_entry *entry;
195 struct fs_fdmi_attrs *hba_attrs;
196 int numattrs = 0;
197 struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
198
199 switch (op) {
200 case FC_FDMI_RHBA:
201 numattrs = 11;
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;
216
217 if (fc_host->fdmi_version == FDMI_V2) {
218 numattrs += 7;
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;
226 }
227
228 ct = fc_ct_hdr_fill(fp, op, req_size: len, fs_type: FC_FST_MGMT,
229 FC_FDMI_SUBTYPE);
230
231 /* HBA Identifier */
232 put_unaligned_be64(val: lport->wwpn, p: &ct->payload.rhba.hbaid.id);
233 /* Number of Ports - always 1 */
234 put_unaligned_be32(val: 1, p: &ct->payload.rhba.port.numport);
235 /* Port Name */
236 put_unaligned_be64(val: lport->wwpn,
237 p: &ct->payload.rhba.port.port[0].portname);
238
239 /* HBA Attributes */
240 put_unaligned_be32(val: numattrs,
241 p: &ct->payload.rhba.hba_attrs.numattrs);
242 hba_attrs = &ct->payload.rhba.hba_attrs;
243 entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
244 /* NodeName*/
245 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
246 len += FC_FDMI_HBA_ATTR_NODENAME_LEN;
247 put_unaligned_be16(val: FC_FDMI_HBA_ATTR_NODENAME,
248 p: &entry->type);
249 put_unaligned_be16(val: len, p: &entry->len);
250 put_unaligned_be64(val: lport->wwnn,
251 p: (__be64 *)&entry->value);
252
253 /* Manufacturer */
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(val: FC_FDMI_HBA_ATTR_MANUFACTURER,
259 p: &entry->type);
260 put_unaligned_be16(val: len, p: &entry->len);
261 fc_ct_ms_fill_attr(entry,
262 fc_host_manufacturer(lport->host),
263 FC_FDMI_HBA_ATTR_MANUFACTURER_LEN);
264
265 /* SerialNumber */
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(val: FC_FDMI_HBA_ATTR_SERIALNUMBER,
271 p: &entry->type);
272 put_unaligned_be16(val: len, p: &entry->len);
273 fc_ct_ms_fill_attr(entry,
274 fc_host_serial_number(lport->host),
275 FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN);
276
277 /* Model */
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(val: FC_FDMI_HBA_ATTR_MODEL,
283 p: &entry->type);
284 put_unaligned_be16(val: len, p: &entry->len);
285 fc_ct_ms_fill_attr(entry,
286 fc_host_model(lport->host),
287 FC_FDMI_HBA_ATTR_MODEL_LEN);
288
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(val: FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
295 p: &entry->type);
296 put_unaligned_be16(val: len, p: &entry->len);
297 fc_ct_ms_fill_attr(entry,
298 fc_host_model_description(lport->host),
299 FC_FDMI_HBA_ATTR_MODELDESCR_LEN);
300
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(val: FC_FDMI_HBA_ATTR_HARDWAREVERSION,
307 p: &entry->type);
308 put_unaligned_be16(val: len, p: &entry->len);
309 fc_ct_ms_fill_attr(entry,
310 fc_host_hardware_version(lport->host),
311 FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN);
312
313 /* Driver Version */
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(val: FC_FDMI_HBA_ATTR_DRIVERVERSION,
319 p: &entry->type);
320 put_unaligned_be16(val: len, p: &entry->len);
321 fc_ct_ms_fill_attr(entry,
322 fc_host_driver_version(lport->host),
323 FC_FDMI_HBA_ATTR_DRIVERVERSION_LEN);
324
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(val: FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
331 p: &entry->type);
332 put_unaligned_be16(val: len, p: &entry->len);
333 fc_ct_ms_fill_attr(entry,
334 in: "unknown",
335 FC_FDMI_HBA_ATTR_OPTIONROMVERSION_LEN);
336
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(val: FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
343 p: &entry->type);
344 put_unaligned_be16(val: len, p: &entry->len);
345 fc_ct_ms_fill_attr(entry,
346 fc_host_firmware_version(lport->host),
347 FC_FDMI_HBA_ATTR_FIRMWAREVERSION_LEN);
348
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(val: FC_FDMI_HBA_ATTR_OSNAMEVERSION,
355 p: &entry->type);
356 put_unaligned_be16(val: len, p: &entry->len);
357 snprintf(buf: (char *)&entry->value,
358 FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
359 fmt: "%s v%s",
360 init_utsname()->sysname,
361 init_utsname()->release);
362
363 /* Max CT payload */
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(val: FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
369 p: &entry->type);
370 put_unaligned_be16(val: len, p: &entry->len);
371 put_unaligned_be32(fc_host_max_ct_payload(lport->host),
372 p: &entry->value);
373
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(val: FC_FDMI_HBA_ATTR_NODESYMBLNAME,
381 p: &entry->type);
382 put_unaligned_be16(val: len, p: &entry->len);
383 fc_ct_ms_fill_attr(entry,
384 fc_host_symbolic_name(lport->host),
385 FC_FDMI_HBA_ATTR_NODESYMBLNAME_LEN);
386
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(val: FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
393 p: &entry->type);
394 put_unaligned_be16(val: len, p: &entry->len);
395 put_unaligned_be32(val: 0,
396 p: &entry->value);
397
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(val: FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
404 p: &entry->type);
405 put_unaligned_be16(val: len, p: &entry->len);
406 put_unaligned_be32(fc_host_num_ports(lport->host),
407 p: &entry->value);
408
409 /* Fabric name */
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(val: FC_FDMI_HBA_ATTR_FABRICNAME,
415 p: &entry->type);
416 put_unaligned_be16(val: len, p: &entry->len);
417 put_unaligned_be64(fc_host_fabric_name(lport->host),
418 p: &entry->value);
419
420 /* BIOS version */
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(val: FC_FDMI_HBA_ATTR_BIOSVERSION,
426 p: &entry->type);
427 put_unaligned_be16(val: len, p: &entry->len);
428 fc_ct_ms_fill_attr(entry,
429 fc_host_bootbios_version(lport->host),
430 FC_FDMI_HBA_ATTR_BIOSVERSION_LEN);
431
432 /* BIOS state */
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(val: FC_FDMI_HBA_ATTR_BIOSSTATE,
438 p: &entry->type);
439 put_unaligned_be16(val: len, p: &entry->len);
440 put_unaligned_be32(fc_host_bootbios_state(lport->host),
441 p: &entry->value);
442
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(val: FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
449 p: &entry->type);
450 put_unaligned_be16(val: len, p: &entry->len);
451 fc_ct_ms_fill_attr(entry,
452 fc_host_vendor_identifier(lport->host),
453 FC_FDMI_HBA_ATTR_VENDORIDENTIFIER_LEN);
454 }
455
456 break;
457 case FC_FDMI_RPA:
458 numattrs = 6;
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;
468
469
470 if (fc_host->fdmi_version == FDMI_V2) {
471 numattrs += 10;
472
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;
483
484 }
485
486 ct = fc_ct_hdr_fill(fp, op, req_size: len, fs_type: FC_FST_MGMT,
487 FC_FDMI_SUBTYPE);
488
489 /* Port Name */
490 put_unaligned_be64(val: lport->wwpn,
491 p: &ct->payload.rpa.port.portname);
492
493 /* Port Attributes */
494 put_unaligned_be32(val: numattrs,
495 p: &ct->payload.rpa.hba_attrs.numattrs);
496
497 hba_attrs = &ct->payload.rpa.hba_attrs;
498 entry = (struct fc_fdmi_attr_entry *)hba_attrs->attr;
499
500 /* FC4 types */
501 len = FC_FDMI_ATTR_ENTRY_HEADER_LEN;
502 len += FC_FDMI_PORT_ATTR_FC4TYPES_LEN;
503 put_unaligned_be16(val: FC_FDMI_PORT_ATTR_FC4TYPES,
504 p: &entry->type);
505 put_unaligned_be16(val: len, p: &entry->len);
506 memcpy(&entry->value, fc_host_supported_fc4s(lport->host),
507 FC_FDMI_PORT_ATTR_FC4TYPES_LEN);
508
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(val: FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
515 p: &entry->type);
516 put_unaligned_be16(val: len, p: &entry->len);
517
518 put_unaligned_be32(fc_host_supported_speeds(lport->host),
519 p: &entry->value);
520
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(val: FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
527 p: &entry->type);
528 put_unaligned_be16(val: len, p: &entry->len);
529 put_unaligned_be32(val: lport->link_speed,
530 p: &entry->value);
531
532 /* Max Frame Size */
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(val: FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
538 p: &entry->type);
539 put_unaligned_be16(val: len, p: &entry->len);
540 put_unaligned_be32(fc_host_maxframe_size(lport->host),
541 p: &entry->value);
542
543 /* OS Device Name */
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(val: FC_FDMI_PORT_ATTR_OSDEVICENAME,
549 p: &entry->type);
550 put_unaligned_be16(val: len, p: &entry->len);
551 /* Use the sysfs device name */
552 fc_ct_ms_fill_attr(entry,
553 in: dev_name(dev: &lport->host->shost_gendev),
554 len: strnlen(p: dev_name(dev: &lport->host->shost_gendev),
555 FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
556
557 /* Host Name */
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(val: FC_FDMI_PORT_ATTR_HOSTNAME,
563 p: &entry->type);
564 put_unaligned_be16(val: len, p: &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 len: strnlen(fc_host_system_hostname(lport->host),
569 FC_FDMI_PORT_ATTR_HOSTNAME_LEN));
570 else
571 fc_ct_ms_fill_attr(entry,
572 in: init_utsname()->nodename,
573 FC_FDMI_PORT_ATTR_HOSTNAME_LEN);
574
575
576 if (fc_host->fdmi_version == FDMI_V2) {
577
578 /* Node name */
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(val: FC_FDMI_PORT_ATTR_NODENAME,
584 p: &entry->type);
585 put_unaligned_be16(val: len, p: &entry->len);
586 put_unaligned_be64(fc_host_node_name(lport->host),
587 p: &entry->value);
588
589 /* Port name */
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(val: FC_FDMI_PORT_ATTR_PORTNAME,
595 p: &entry->type);
596 put_unaligned_be16(val: len, p: &entry->len);
597 put_unaligned_be64(val: lport->wwpn,
598 p: &entry->value);
599
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(val: FC_FDMI_PORT_ATTR_SYMBOLICNAME,
606 p: &entry->type);
607 put_unaligned_be16(val: len, p: &entry->len);
608 fc_ct_ms_fill_attr(entry,
609 fc_host_symbolic_name(lport->host),
610 FC_FDMI_PORT_ATTR_SYMBOLICNAME_LEN);
611
612 /* Port type */
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(val: FC_FDMI_PORT_ATTR_PORTTYPE,
618 p: &entry->type);
619 put_unaligned_be16(val: len, p: &entry->len);
620 put_unaligned_be32(fc_host_port_type(lport->host),
621 p: &entry->value);
622
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(val: FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
629 p: &entry->type);
630 put_unaligned_be16(val: len, p: &entry->len);
631 put_unaligned_be32(fc_host_supported_classes(lport->host),
632 p: &entry->value);
633
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(val: FC_FDMI_PORT_ATTR_FABRICNAME,
640 p: &entry->type);
641 put_unaligned_be16(val: len, p: &entry->len);
642 put_unaligned_be64(fc_host_fabric_name(lport->host),
643 p: &entry->value);
644
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(val: FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
651 p: &entry->type);
652 put_unaligned_be16(val: len, p: &entry->len);
653 memcpy(&entry->value, fc_host_active_fc4s(lport->host),
654 FC_FDMI_PORT_ATTR_CURRENTFC4TYPE_LEN);
655
656 /* Port state */
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(val: FC_FDMI_PORT_ATTR_PORTSTATE,
662 p: &entry->type);
663 put_unaligned_be16(val: len, p: &entry->len);
664 put_unaligned_be32(fc_host_port_state(lport->host),
665 p: &entry->value);
666
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(val: FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
673 p: &entry->type);
674 put_unaligned_be16(val: len, p: &entry->len);
675 put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
676 p: &entry->value);
677
678 /* Port ID */
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(val: FC_FDMI_PORT_ATTR_PORTID,
684 p: &entry->type);
685 put_unaligned_be16(val: len, p: &entry->len);
686 put_unaligned_be32(fc_host_port_id(lport->host),
687 p: &entry->value);
688 }
689
690 break;
691 case FC_FDMI_DPRT:
692 len = sizeof(struct fc_fdmi_dprt);
693 ct = fc_ct_hdr_fill(fp, op, req_size: len, fs_type: FC_FST_MGMT,
694 FC_FDMI_SUBTYPE);
695 /* Port Name */
696 put_unaligned_be64(val: lport->wwpn,
697 p: &ct->payload.dprt.port.portname);
698 break;
699 case FC_FDMI_DHBA:
700 len = sizeof(struct fc_fdmi_dhba);
701 ct = fc_ct_hdr_fill(fp, op, req_size: len, fs_type: FC_FST_MGMT,
702 FC_FDMI_SUBTYPE);
703 /* HBA Identifier */
704 put_unaligned_be64(val: lport->wwpn, p: &ct->payload.dhba.hbaid.id);
705 break;
706 default:
707 return -EINVAL;
708 }
709 *r_ctl = FC_RCTL_DD_UNSOL_CTL;
710 *fh_type = FC_TYPE_CT;
711 return 0;
712}
713
714/**
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.
719 * @op: CT opcode.
720 * @r_ctl: pointer to FC header R_CTL.
721 * @fh_type: pointer to FC-4 type.
722 */
723static 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)
727{
728 int rc = -EINVAL;
729
730 switch (fc_id) {
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;
734 break;
735 case FC_FID_DIR_SERV:
736 default:
737 rc = fc_ct_ns_fill(lport, fc_id, fp, op, r_ctl, fh_type);
738 *did = FC_FID_DIR_SERV;
739 break;
740 }
741
742 return rc;
743}
744/**
745 * fc_plogi_fill - Fill in plogi request frame
746 */
747static inline void fc_plogi_fill(struct fc_lport *lport, struct fc_frame *fp,
748 unsigned int op)
749{
750 struct fc_els_flogi *plogi;
751 struct fc_els_csp *csp;
752 struct fc_els_cssp *cp;
753
754 plogi = fc_frame_payload_get(fp, len: sizeof(*plogi));
755 memset(plogi, 0, sizeof(*plogi));
756 plogi->fl_cmd = (u8) op;
757 put_unaligned_be64(val: lport->wwpn, p: &plogi->fl_wwpn);
758 put_unaligned_be64(val: lport->wwnn, p: &plogi->fl_wwnn);
759
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);
771
772 cp->cp_rdfs = htons((u16) lport->mfs);
773 cp->cp_con_seq = htons(255);
774 cp->cp_open_seq = 1;
775}
776
777/**
778 * fc_flogi_fill - Fill in a flogi request frame.
779 */
780static inline void fc_flogi_fill(struct fc_lport *lport, struct fc_frame *fp)
781{
782 struct fc_els_csp *sp;
783 struct fc_els_cssp *cp;
784 struct fc_els_flogi *flogi;
785
786 flogi = fc_frame_payload_get(fp, len: sizeof(*flogi));
787 memset(flogi, 0, sizeof(*flogi));
788 flogi->fl_cmd = (u8) ELS_FLOGI;
789 put_unaligned_be64(val: lport->wwpn, p: &flogi->fl_wwpn);
790 put_unaligned_be64(val: lport->wwnn, p: &flogi->fl_wwnn);
791 sp = &flogi->fl_csp;
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);
800}
801
802/**
803 * fc_fdisc_fill - Fill in a fdisc request frame.
804 */
805static inline void fc_fdisc_fill(struct fc_lport *lport, struct fc_frame *fp)
806{
807 struct fc_els_csp *sp;
808 struct fc_els_cssp *cp;
809 struct fc_els_flogi *fdisc;
810
811 fdisc = fc_frame_payload_get(fp, len: sizeof(*fdisc));
812 memset(fdisc, 0, sizeof(*fdisc));
813 fdisc->fl_cmd = (u8) ELS_FDISC;
814 put_unaligned_be64(val: lport->wwpn, p: &fdisc->fl_wwpn);
815 put_unaligned_be64(val: lport->wwnn, p: &fdisc->fl_wwnn);
816 sp = &fdisc->fl_csp;
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);
823}
824
825/**
826 * fc_logo_fill - Fill in a logo request frame.
827 */
828static inline void fc_logo_fill(struct fc_lport *lport, struct fc_frame *fp)
829{
830 struct fc_els_logo *;
831
832 logo = fc_frame_payload_get(fp, len: sizeof(*logo));
833 memset(logo, 0, sizeof(*logo));
834 logo->fl_cmd = ELS_LOGO;
835 hton24(p: logo->fl_n_port_id, v: lport->port_id);
836 logo->fl_n_port_wwn = htonll(lport->wwpn);
837}
838
839/**
840 * fc_rtv_fill - Fill in RTV (read timeout value) request frame.
841 */
842static inline void fc_rtv_fill(struct fc_lport *lport, struct fc_frame *fp)
843{
844 struct fc_els_rtv *rtv;
845
846 rtv = fc_frame_payload_get(fp, len: sizeof(*rtv));
847 memset(rtv, 0, sizeof(*rtv));
848 rtv->rtv_cmd = ELS_RTV;
849}
850
851/**
852 * fc_rec_fill - Fill in rec request frame
853 */
854static inline void fc_rec_fill(struct fc_lport *lport, struct fc_frame *fp)
855{
856 struct fc_els_rec *rec;
857 struct fc_exch *ep = fc_seq_exch(fr_seq(fp));
858
859 rec = fc_frame_payload_get(fp, len: sizeof(*rec));
860 memset(rec, 0, sizeof(*rec));
861 rec->rec_cmd = ELS_REC;
862 hton24(p: rec->rec_s_id, v: lport->port_id);
863 rec->rec_ox_id = htons(ep->oxid);
864 rec->rec_rx_id = htons(ep->rxid);
865}
866
867/**
868 * fc_prli_fill - Fill in prli request frame
869 */
870static inline void fc_prli_fill(struct fc_lport *lport, struct fc_frame *fp)
871{
872 struct {
873 struct fc_els_prli prli;
874 struct fc_els_spp spp;
875 } *pp;
876
877 pp = fc_frame_payload_get(fp, len: 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);
885}
886
887/**
888 * fc_scr_fill - Fill in a scr request frame.
889 */
890static inline void fc_scr_fill(struct fc_lport *lport, struct fc_frame *fp)
891{
892 struct fc_els_scr *scr;
893
894 scr = fc_frame_payload_get(fp, len: sizeof(*scr));
895 memset(scr, 0, sizeof(*scr));
896 scr->scr_cmd = ELS_SCR;
897 scr->scr_reg_func = ELS_SCRF_FULL;
898}
899
900/**
901 * fc_els_fill - Fill in an ELS request frame
902 */
903static inline int fc_els_fill(struct fc_lport *lport,
904 u32 did,
905 struct fc_frame *fp, unsigned int op,
906 enum fc_rctl *r_ctl, enum fc_fh_type *fh_type)
907{
908 switch (op) {
909 case ELS_ADISC:
910 fc_adisc_fill(lport, fp);
911 break;
912
913 case ELS_PLOGI:
914 fc_plogi_fill(lport, fp, op: ELS_PLOGI);
915 break;
916
917 case ELS_FLOGI:
918 fc_flogi_fill(lport, fp);
919 break;
920
921 case ELS_FDISC:
922 fc_fdisc_fill(lport, fp);
923 break;
924
925 case ELS_LOGO:
926 fc_logo_fill(lport, fp);
927 break;
928
929 case ELS_RTV:
930 fc_rtv_fill(lport, fp);
931 break;
932
933 case ELS_REC:
934 fc_rec_fill(lport, fp);
935 break;
936
937 case ELS_PRLI:
938 fc_prli_fill(lport, fp);
939 break;
940
941 case ELS_SCR:
942 fc_scr_fill(lport, fp);
943 break;
944
945 default:
946 return -EINVAL;
947 }
948
949 *r_ctl = FC_RCTL_ELS_REQ;
950 *fh_type = FC_TYPE_ELS;
951 return 0;
952}
953#endif /* _FC_ENCODE_H_ */
954

source code of linux/drivers/scsi/libfc/fc_encode.h