Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 <linux/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, 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);
 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, 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, sizeof(struct fc_ns_gid_ft),
102				    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, 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);
111		break;
112
113	case FC_NS_RFT_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;
118		break;
119
120	case FC_NS_RFF_ID:
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;
129		break;
130
131	case FC_NS_RNN_ID:
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);
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, 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;
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, 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;
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, len, FC_FST_MGMT,
229				FC_FDMI_SUBTYPE);
230
231		/* HBA Identifier */
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);
235		/* Port Name */
236		put_unaligned_be64(lport->wwpn,
237				   &ct->payload.rhba.port.port[0].portname);
238
239		/* HBA Attributes */
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;
244		/* NodeName*/
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,
248				   &entry->type);
249		put_unaligned_be16(len, &entry->len);
250		put_unaligned_be64(lport->wwnn,
251				   (__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(FC_FDMI_HBA_ATTR_MANUFACTURER,
259				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_SERIALNUMBER,
271				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_MODEL,
283				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_MODELDESCRIPTION,
295				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_HARDWAREVERSION,
307				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_DRIVERVERSION,
319				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_OPTIONROMVERSION,
331				   &entry->type);
332		put_unaligned_be16(len, &entry->len);
333		fc_ct_ms_fill_attr(entry,
334			"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(FC_FDMI_HBA_ATTR_FIRMWAREVERSION,
343				   &entry->type);
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);
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(FC_FDMI_HBA_ATTR_OSNAMEVERSION,
355				   &entry->type);
356		put_unaligned_be16(len, &entry->len);
357		snprintf((char *)&entry->value,
358			FC_FDMI_HBA_ATTR_OSNAMEVERSION_LEN,
359			"%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(FC_FDMI_HBA_ATTR_MAXCTPAYLOAD,
369				&entry->type);
370		put_unaligned_be16(len, &entry->len);
371		put_unaligned_be32(fc_host_max_ct_payload(lport->host),
372				&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(FC_FDMI_HBA_ATTR_NODESYMBLNAME,
381					&entry->type);
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);
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(FC_FDMI_HBA_ATTR_VENDORSPECIFICINFO,
393					&entry->type);
394			put_unaligned_be16(len, &entry->len);
395			put_unaligned_be32(0,
396					&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(FC_FDMI_HBA_ATTR_NUMBEROFPORTS,
404					&entry->type);
405			put_unaligned_be16(len, &entry->len);
406			put_unaligned_be32(fc_host_num_ports(lport->host),
407					&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(FC_FDMI_HBA_ATTR_FABRICNAME,
415					&entry->type);
416			put_unaligned_be16(len, &entry->len);
417			put_unaligned_be64(fc_host_fabric_name(lport->host),
418					&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(FC_FDMI_HBA_ATTR_BIOSVERSION,
426					&entry->type);
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);
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(FC_FDMI_HBA_ATTR_BIOSSTATE,
438					&entry->type);
439			put_unaligned_be16(len, &entry->len);
440			put_unaligned_be32(fc_host_bootbios_state(lport->host),
441					&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(FC_FDMI_HBA_ATTR_VENDORIDENTIFIER,
449					&entry->type);
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);
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, len, FC_FST_MGMT,
487				    FC_FDMI_SUBTYPE);
488
489		/* Port Name */
490		put_unaligned_be64(lport->wwpn,
491				   &ct->payload.rpa.port.portname);
492
493		/* Port Attributes */
494		put_unaligned_be32(numattrs,
495				   &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(FC_FDMI_PORT_ATTR_FC4TYPES,
504				   &entry->type);
505		put_unaligned_be16(len, &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(FC_FDMI_PORT_ATTR_SUPPORTEDSPEED,
515				   &entry->type);
516		put_unaligned_be16(len, &entry->len);
517
518		put_unaligned_be32(fc_host_supported_speeds(lport->host),
519				   &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(FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
527				   &entry->type);
528		put_unaligned_be16(len, &entry->len);
529		put_unaligned_be32(lport->link_speed,
530				   &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(FC_FDMI_PORT_ATTR_MAXFRAMESIZE,
538				   &entry->type);
539		put_unaligned_be16(len, &entry->len);
540		put_unaligned_be32(fc_host_maxframe_size(lport->host),
541				   &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(FC_FDMI_PORT_ATTR_OSDEVICENAME,
549				   &entry->type);
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));
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(FC_FDMI_PORT_ATTR_HOSTNAME,
563				   &entry->type);
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));
570		else
571			fc_ct_ms_fill_attr(entry,
572				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(FC_FDMI_PORT_ATTR_NODENAME,
584					&entry->type);
585			put_unaligned_be16(len, &entry->len);
586			put_unaligned_be64(fc_host_node_name(lport->host),
587					&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(FC_FDMI_PORT_ATTR_PORTNAME,
595					&entry->type);
596			put_unaligned_be16(len, &entry->len);
597			put_unaligned_be64(lport->wwpn,
598					&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(FC_FDMI_PORT_ATTR_SYMBOLICNAME,
606					&entry->type);
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);
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(FC_FDMI_PORT_ATTR_PORTTYPE,
618					&entry->type);
619			put_unaligned_be16(len, &entry->len);
620			put_unaligned_be32(fc_host_port_type(lport->host),
621					&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(FC_FDMI_PORT_ATTR_SUPPORTEDCLASSSRVC,
629					&entry->type);
630			put_unaligned_be16(len, &entry->len);
631			put_unaligned_be32(fc_host_supported_classes(lport->host),
632					&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(FC_FDMI_PORT_ATTR_FABRICNAME,
640					&entry->type);
641			put_unaligned_be16(len, &entry->len);
642			put_unaligned_be64(fc_host_fabric_name(lport->host),
643					&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(FC_FDMI_PORT_ATTR_CURRENTFC4TYPE,
651					&entry->type);
652			put_unaligned_be16(len, &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(FC_FDMI_PORT_ATTR_PORTSTATE,
662					&entry->type);
663			put_unaligned_be16(len, &entry->len);
664			put_unaligned_be32(fc_host_port_state(lport->host),
665					&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(FC_FDMI_PORT_ATTR_DISCOVEREDPORTS,
673					&entry->type);
674			put_unaligned_be16(len, &entry->len);
675			put_unaligned_be32(fc_host_num_discovered_ports(lport->host),
676					&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(FC_FDMI_PORT_ATTR_PORTID,
684					&entry->type);
685			put_unaligned_be16(len, &entry->len);
686			put_unaligned_be32(fc_host_port_id(lport->host),
687					&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, len, FC_FST_MGMT,
694				    FC_FDMI_SUBTYPE);
695		/* Port Name */
696		put_unaligned_be64(lport->wwpn,
697				   &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, len, FC_FST_MGMT,
702				    FC_FDMI_SUBTYPE);
703		/* HBA Identifier */
704		put_unaligned_be64(lport->wwpn, &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, 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);
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, 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);
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, 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);
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 *logo;
831
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);
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, 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, 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);
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, 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, 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, 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_ */