xref: /openbmc/linux/drivers/scsi/bfa/bfa_fcbuild.c (revision dea54fba)
1 /*
2  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
3  * Copyright (c) 2014- QLogic Corporation.
4  * All rights reserved
5  * www.qlogic.com
6  *
7  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License (GPL) Version 2 as
11  * published by the Free Software Foundation
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  */
18 /*
19  * fcbuild.c - FC link service frame building and parsing routines
20  */
21 
22 #include "bfad_drv.h"
23 #include "bfa_fcbuild.h"
24 
25 /*
26  * static build functions
27  */
28 static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
29 				 __be16 ox_id);
30 static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
31 				 __be16 ox_id);
32 static struct fchs_s fc_els_req_tmpl;
33 static struct fchs_s fc_els_rsp_tmpl;
34 static struct fchs_s fc_bls_req_tmpl;
35 static struct fchs_s fc_bls_rsp_tmpl;
36 static struct fc_ba_acc_s ba_acc_tmpl;
37 static struct fc_logi_s plogi_tmpl;
38 static struct fc_prli_s prli_tmpl;
39 static struct fc_rrq_s rrq_tmpl;
40 static struct fchs_s fcp_fchs_tmpl;
41 
42 void
43 fcbuild_init(void)
44 {
45 	/*
46 	 * fc_els_req_tmpl
47 	 */
48 	fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
49 	fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
50 	fc_els_req_tmpl.type = FC_TYPE_ELS;
51 	fc_els_req_tmpl.f_ctl =
52 		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
53 			      FCTL_SI_XFER);
54 	fc_els_req_tmpl.rx_id = FC_RXID_ANY;
55 
56 	/*
57 	 * fc_els_rsp_tmpl
58 	 */
59 	fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
60 	fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
61 	fc_els_rsp_tmpl.type = FC_TYPE_ELS;
62 	fc_els_rsp_tmpl.f_ctl =
63 		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
64 			      FCTL_END_SEQ | FCTL_SI_XFER);
65 	fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
66 
67 	/*
68 	 * fc_bls_req_tmpl
69 	 */
70 	fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
71 	fc_bls_req_tmpl.type = FC_TYPE_BLS;
72 	fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
73 	fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
74 
75 	/*
76 	 * fc_bls_rsp_tmpl
77 	 */
78 	fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
79 	fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
80 	fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
81 	fc_bls_rsp_tmpl.f_ctl =
82 		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
83 			      FCTL_END_SEQ | FCTL_SI_XFER);
84 	fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
85 
86 	/*
87 	 * ba_acc_tmpl
88 	 */
89 	ba_acc_tmpl.seq_id_valid = 0;
90 	ba_acc_tmpl.low_seq_cnt = 0;
91 	ba_acc_tmpl.high_seq_cnt = 0xFFFF;
92 
93 	/*
94 	 * plogi_tmpl
95 	 */
96 	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
97 	plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
98 	plogi_tmpl.csp.ciro = 0x1;
99 	plogi_tmpl.csp.cisc = 0x0;
100 	plogi_tmpl.csp.altbbcred = 0x0;
101 	plogi_tmpl.csp.conseq = cpu_to_be16(0x00FF);
102 	plogi_tmpl.csp.ro_bitmap = cpu_to_be16(0x0002);
103 	plogi_tmpl.csp.e_d_tov = cpu_to_be32(2000);
104 
105 	plogi_tmpl.class3.class_valid = 1;
106 	plogi_tmpl.class3.sequential = 1;
107 	plogi_tmpl.class3.conseq = 0xFF;
108 	plogi_tmpl.class3.ospx = 1;
109 
110 	/*
111 	 * prli_tmpl
112 	 */
113 	prli_tmpl.command = FC_ELS_PRLI;
114 	prli_tmpl.pglen = 0x10;
115 	prli_tmpl.pagebytes = cpu_to_be16(0x0014);
116 	prli_tmpl.parampage.type = FC_TYPE_FCP;
117 	prli_tmpl.parampage.imagepair = 1;
118 	prli_tmpl.parampage.servparams.rxrdisab = 1;
119 
120 	/*
121 	 * rrq_tmpl
122 	 */
123 	rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
124 
125 	/*
126 	 * fcp_struct fchs_s mpl
127 	 */
128 	fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
129 	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
130 	fcp_fchs_tmpl.type = FC_TYPE_FCP;
131 	fcp_fchs_tmpl.f_ctl =
132 		bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
133 	fcp_fchs_tmpl.seq_id = 1;
134 	fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
135 }
136 
137 static void
138 fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
139 {
140 	memset(fchs, 0, sizeof(struct fchs_s));
141 
142 	fchs->routing = FC_RTG_FC4_DEV_DATA;
143 	fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
144 	fchs->type = FC_TYPE_SERVICES;
145 	fchs->f_ctl =
146 		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
147 			      FCTL_SI_XFER);
148 	fchs->rx_id = FC_RXID_ANY;
149 	fchs->d_id = (d_id);
150 	fchs->s_id = (s_id);
151 	fchs->ox_id = cpu_to_be16(ox_id);
152 
153 	/*
154 	 * @todo no need to set ox_id for request
155 	 *       no need to set rx_id for response
156 	 */
157 }
158 
159 static void
160 fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
161 {
162 	memset(fchs, 0, sizeof(struct fchs_s));
163 
164 	fchs->routing = FC_RTG_FC4_DEV_DATA;
165 	fchs->cat_info = FC_CAT_SOLICIT_CTRL;
166 	fchs->type = FC_TYPE_SERVICES;
167 	fchs->f_ctl =
168 		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
169 			   FCTL_END_SEQ | FCTL_SI_XFER);
170 	fchs->d_id = d_id;
171 	fchs->s_id = s_id;
172 	fchs->ox_id = ox_id;
173 }
174 
175 void
176 fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
177 {
178 	memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
179 	fchs->d_id = (d_id);
180 	fchs->s_id = (s_id);
181 	fchs->ox_id = cpu_to_be16(ox_id);
182 }
183 
184 static void
185 fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
186 {
187 	memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
188 	fchs->d_id = d_id;
189 	fchs->s_id = s_id;
190 	fchs->ox_id = ox_id;
191 }
192 
193 enum fc_parse_status
194 fc_els_rsp_parse(struct fchs_s *fchs, int len)
195 {
196 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
197 	struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd;
198 
199 	len = len;
200 
201 	switch (els_cmd->els_code) {
202 	case FC_ELS_LS_RJT:
203 		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
204 			return FC_PARSE_BUSY;
205 		else
206 			return FC_PARSE_FAILURE;
207 
208 	case FC_ELS_ACC:
209 		return FC_PARSE_OK;
210 	}
211 	return FC_PARSE_OK;
212 }
213 
214 static void
215 fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
216 {
217 	memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
218 	fchs->d_id = d_id;
219 	fchs->s_id = s_id;
220 	fchs->ox_id = ox_id;
221 }
222 
223 static          u16
224 fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
225 		 __be16 ox_id, wwn_t port_name, wwn_t node_name,
226 		 u16 pdu_size, u16 bb_cr, u8 els_code)
227 {
228 	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
229 
230 	memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
231 
232 	/* For FC AL bb_cr is 0 and altbbcred is 1 */
233 	if (!bb_cr)
234 		plogi->csp.altbbcred = 1;
235 
236 	plogi->els_cmd.els_code = els_code;
237 	if (els_code == FC_ELS_PLOGI)
238 		fc_els_req_build(fchs, d_id, s_id, ox_id);
239 	else
240 		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
241 
242 	plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
243 	plogi->csp.bbcred  = cpu_to_be16(bb_cr);
244 
245 	memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
246 	memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
247 
248 	return sizeof(struct fc_logi_s);
249 }
250 
251 u16
252 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
253 		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
254 	       u8 set_npiv, u8 set_auth, u16 local_bb_credits)
255 {
256 	u32        d_id = bfa_hton3b(FC_FABRIC_PORT);
257 	__be32	*vvl_info;
258 
259 	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
260 
261 	flogi->els_cmd.els_code = FC_ELS_FLOGI;
262 	fc_els_req_build(fchs, d_id, s_id, ox_id);
263 
264 	flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
265 	flogi->port_name = port_name;
266 	flogi->node_name = node_name;
267 
268 	/*
269 	 * Set the NPIV Capability Bit ( word 1, bit 31) of Common
270 	 * Service Parameters.
271 	 */
272 	flogi->csp.ciro = set_npiv;
273 
274 	/* set AUTH capability */
275 	flogi->csp.security = set_auth;
276 
277 	flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
278 
279 	/* Set brcd token in VVL */
280 	vvl_info = (u32 *)&flogi->vvl[0];
281 
282 	/* set the flag to indicate the presence of VVL */
283 	flogi->csp.npiv_supp    = 1; /* @todo. field name is not correct */
284 	vvl_info[0]	= cpu_to_be32(FLOGI_VVL_BRCD);
285 
286 	return sizeof(struct fc_logi_s);
287 }
288 
289 u16
290 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
291 		   __be16 ox_id, wwn_t port_name, wwn_t node_name,
292 		   u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
293 {
294 	u32        d_id = 0;
295 	u16	   bbscn_rxsz = (bb_scn << 12) | pdu_size;
296 
297 	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
298 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
299 
300 	flogi->els_cmd.els_code = FC_ELS_ACC;
301 	flogi->class3.rxsz = cpu_to_be16(pdu_size);
302 	flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);	/* bb_scn/rxsz */
303 	flogi->port_name = port_name;
304 	flogi->node_name = node_name;
305 
306 	flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
307 
308 	return sizeof(struct fc_logi_s);
309 }
310 
311 u16
312 fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
313 		u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
314 {
315 	u32        d_id = bfa_hton3b(FC_FABRIC_PORT);
316 
317 	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
318 
319 	flogi->els_cmd.els_code = FC_ELS_FDISC;
320 	fc_els_req_build(fchs, d_id, s_id, ox_id);
321 
322 	flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
323 	flogi->port_name = port_name;
324 	flogi->node_name = node_name;
325 
326 	return sizeof(struct fc_logi_s);
327 }
328 
329 u16
330 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
331 	       u16 ox_id, wwn_t port_name, wwn_t node_name,
332 	       u16 pdu_size, u16 bb_cr)
333 {
334 	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
335 				node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
336 }
337 
338 u16
339 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
340 		   u16 ox_id, wwn_t port_name, wwn_t node_name,
341 		   u16 pdu_size, u16 bb_cr)
342 {
343 	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
344 				node_name, pdu_size, bb_cr, FC_ELS_ACC);
345 }
346 
347 enum fc_parse_status
348 fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
349 {
350 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
351 	struct fc_logi_s *plogi;
352 	struct fc_ls_rjt_s *ls_rjt;
353 
354 	switch (els_cmd->els_code) {
355 	case FC_ELS_LS_RJT:
356 		ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
357 		if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
358 			return FC_PARSE_BUSY;
359 		else
360 			return FC_PARSE_FAILURE;
361 	case FC_ELS_ACC:
362 		plogi = (struct fc_logi_s *) (fchs + 1);
363 		if (len < sizeof(struct fc_logi_s))
364 			return FC_PARSE_FAILURE;
365 
366 		if (!wwn_is_equal(plogi->port_name, port_name))
367 			return FC_PARSE_FAILURE;
368 
369 		if (!plogi->class3.class_valid)
370 			return FC_PARSE_FAILURE;
371 
372 		if (be16_to_cpu(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
373 			return FC_PARSE_FAILURE;
374 
375 		return FC_PARSE_OK;
376 	default:
377 		return FC_PARSE_FAILURE;
378 	}
379 }
380 
381 enum fc_parse_status
382 fc_plogi_parse(struct fchs_s *fchs)
383 {
384 	struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
385 
386 	if (plogi->class3.class_valid != 1)
387 		return FC_PARSE_FAILURE;
388 
389 	if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ)
390 	    || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ)
391 	    || (plogi->class3.rxsz == 0))
392 		return FC_PARSE_FAILURE;
393 
394 	return FC_PARSE_OK;
395 }
396 
397 u16
398 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
399 	      u16 ox_id)
400 {
401 	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
402 
403 	fc_els_req_build(fchs, d_id, s_id, ox_id);
404 	memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
405 
406 	prli->command = FC_ELS_PRLI;
407 	prli->parampage.servparams.initiator     = 1;
408 	prli->parampage.servparams.retry         = 1;
409 	prli->parampage.servparams.rec_support   = 1;
410 	prli->parampage.servparams.task_retry_id = 0;
411 	prli->parampage.servparams.confirm       = 1;
412 
413 	return sizeof(struct fc_prli_s);
414 }
415 
416 u16
417 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
418 		  __be16 ox_id, enum bfa_lport_role role)
419 {
420 	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
421 
422 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
423 	memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
424 
425 	prli->command = FC_ELS_ACC;
426 
427 	prli->parampage.servparams.initiator = 1;
428 
429 	prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
430 
431 	return sizeof(struct fc_prli_s);
432 }
433 
434 enum fc_parse_status
435 fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
436 {
437 	if (len < sizeof(struct fc_prli_s))
438 		return FC_PARSE_FAILURE;
439 
440 	if (prli->command != FC_ELS_ACC)
441 		return FC_PARSE_FAILURE;
442 
443 	if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
444 	    && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
445 		return FC_PARSE_FAILURE;
446 
447 	if (prli->parampage.servparams.target != 1)
448 		return FC_PARSE_FAILURE;
449 
450 	return FC_PARSE_OK;
451 }
452 
453 enum fc_parse_status
454 fc_prli_parse(struct fc_prli_s *prli)
455 {
456 	if (prli->parampage.type != FC_TYPE_FCP)
457 		return FC_PARSE_FAILURE;
458 
459 	if (!prli->parampage.imagepair)
460 		return FC_PARSE_FAILURE;
461 
462 	if (!prli->parampage.servparams.initiator)
463 		return FC_PARSE_FAILURE;
464 
465 	return FC_PARSE_OK;
466 }
467 
468 u16
469 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
470 	      u16 ox_id, wwn_t port_name)
471 {
472 	fc_els_req_build(fchs, d_id, s_id, ox_id);
473 
474 	memset(logo, '\0', sizeof(struct fc_logo_s));
475 	logo->els_cmd.els_code = FC_ELS_LOGO;
476 	logo->nport_id = (s_id);
477 	logo->orig_port_name = port_name;
478 
479 	return sizeof(struct fc_logo_s);
480 }
481 
482 static u16
483 fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
484 		 u32 s_id, __be16 ox_id, wwn_t port_name,
485 		 wwn_t node_name, u8 els_code)
486 {
487 	memset(adisc, '\0', sizeof(struct fc_adisc_s));
488 
489 	adisc->els_cmd.els_code = els_code;
490 
491 	if (els_code == FC_ELS_ADISC)
492 		fc_els_req_build(fchs, d_id, s_id, ox_id);
493 	else
494 		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
495 
496 	adisc->orig_HA = 0;
497 	adisc->orig_port_name = port_name;
498 	adisc->orig_node_name = node_name;
499 	adisc->nport_id = (s_id);
500 
501 	return sizeof(struct fc_adisc_s);
502 }
503 
504 u16
505 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
506 		u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
507 {
508 	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
509 				node_name, FC_ELS_ADISC);
510 }
511 
512 u16
513 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
514 		   u32 s_id, __be16 ox_id, wwn_t port_name,
515 		   wwn_t node_name)
516 {
517 	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
518 				node_name, FC_ELS_ACC);
519 }
520 
521 enum fc_parse_status
522 fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
523 				 wwn_t node_name)
524 {
525 
526 	if (len < sizeof(struct fc_adisc_s))
527 		return FC_PARSE_FAILURE;
528 
529 	if (adisc->els_cmd.els_code != FC_ELS_ACC)
530 		return FC_PARSE_FAILURE;
531 
532 	if (!wwn_is_equal(adisc->orig_port_name, port_name))
533 		return FC_PARSE_FAILURE;
534 
535 	return FC_PARSE_OK;
536 }
537 
538 enum fc_parse_status
539 fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
540 	       wwn_t port_name)
541 {
542 	struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
543 
544 	if (adisc->els_cmd.els_code != FC_ELS_ACC)
545 		return FC_PARSE_FAILURE;
546 
547 	if ((adisc->nport_id == (host_dap))
548 	    && wwn_is_equal(adisc->orig_port_name, port_name)
549 	    && wwn_is_equal(adisc->orig_node_name, node_name))
550 		return FC_PARSE_OK;
551 
552 	return FC_PARSE_FAILURE;
553 }
554 
555 enum fc_parse_status
556 fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
557 {
558 	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
559 
560 	if (pdisc->class3.class_valid != 1)
561 		return FC_PARSE_FAILURE;
562 
563 	if ((be16_to_cpu(pdisc->class3.rxsz) <
564 		(FC_MIN_PDUSZ - sizeof(struct fchs_s)))
565 	    || (pdisc->class3.rxsz == 0))
566 		return FC_PARSE_FAILURE;
567 
568 	if (!wwn_is_equal(pdisc->port_name, port_name))
569 		return FC_PARSE_FAILURE;
570 
571 	if (!wwn_is_equal(pdisc->node_name, node_name))
572 		return FC_PARSE_FAILURE;
573 
574 	return FC_PARSE_OK;
575 }
576 
577 u16
578 fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
579 {
580 	memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
581 	fchs->cat_info = FC_CAT_ABTS;
582 	fchs->d_id = (d_id);
583 	fchs->s_id = (s_id);
584 	fchs->ox_id = cpu_to_be16(ox_id);
585 
586 	return sizeof(struct fchs_s);
587 }
588 
589 enum fc_parse_status
590 fc_abts_rsp_parse(struct fchs_s *fchs, int len)
591 {
592 	if ((fchs->cat_info == FC_CAT_BA_ACC)
593 	    || (fchs->cat_info == FC_CAT_BA_RJT))
594 		return FC_PARSE_OK;
595 
596 	return FC_PARSE_FAILURE;
597 }
598 
599 u16
600 fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
601 	     u16 ox_id, u16 rrq_oxid)
602 {
603 	fc_els_req_build(fchs, d_id, s_id, ox_id);
604 
605 	/*
606 	 * build rrq payload
607 	 */
608 	memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
609 	rrq->s_id = (s_id);
610 	rrq->ox_id = cpu_to_be16(rrq_oxid);
611 	rrq->rx_id = FC_RXID_ANY;
612 
613 	return sizeof(struct fc_rrq_s);
614 }
615 
616 u16
617 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
618 		  __be16 ox_id)
619 {
620 	struct fc_els_cmd_s *acc = pld;
621 
622 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
623 
624 	memset(acc, 0, sizeof(struct fc_els_cmd_s));
625 	acc->els_code = FC_ELS_ACC;
626 
627 	return sizeof(struct fc_els_cmd_s);
628 }
629 
630 u16
631 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
632 		u32 s_id, __be16 ox_id, u8 reason_code,
633 		u8 reason_code_expl)
634 {
635 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
636 	memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
637 
638 	ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
639 	ls_rjt->reason_code = reason_code;
640 	ls_rjt->reason_code_expl = reason_code_expl;
641 	ls_rjt->vendor_unique = 0x00;
642 
643 	return sizeof(struct fc_ls_rjt_s);
644 }
645 
646 u16
647 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
648 		u32 s_id, __be16 ox_id, u16 rx_id)
649 {
650 	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
651 
652 	memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
653 
654 	fchs->rx_id = rx_id;
655 
656 	ba_acc->ox_id = fchs->ox_id;
657 	ba_acc->rx_id = fchs->rx_id;
658 
659 	return sizeof(struct fc_ba_acc_s);
660 }
661 
662 u16
663 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
664 		u32 s_id, __be16 ox_id)
665 {
666 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
667 	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
668 	els_cmd->els_code = FC_ELS_ACC;
669 
670 	return sizeof(struct fc_els_cmd_s);
671 }
672 
673 int
674 fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
675 {
676 	int             num_pages = 0;
677 	struct fc_prlo_s *prlo;
678 	struct fc_tprlo_s *tprlo;
679 
680 	if (els_code == FC_ELS_PRLO) {
681 		prlo = (struct fc_prlo_s *) (fc_frame + 1);
682 		num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16;
683 	} else {
684 		tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
685 		num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
686 	}
687 	return num_pages;
688 }
689 
690 u16
691 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
692 		u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
693 {
694 	int             page;
695 
696 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
697 
698 	memset(tprlo_acc, 0, (num_pages * 16) + 4);
699 	tprlo_acc->command = FC_ELS_ACC;
700 
701 	tprlo_acc->page_len = 0x10;
702 	tprlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
703 
704 	for (page = 0; page < num_pages; page++) {
705 		tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
706 		tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
707 		tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
708 		tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
709 		tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
710 	}
711 	return be16_to_cpu(tprlo_acc->payload_len);
712 }
713 
714 u16
715 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
716 		  u32 s_id, __be16 ox_id, int num_pages)
717 {
718 	int             page;
719 
720 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
721 
722 	memset(prlo_acc, 0, (num_pages * 16) + 4);
723 	prlo_acc->command = FC_ELS_ACC;
724 	prlo_acc->page_len = 0x10;
725 	prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
726 
727 	for (page = 0; page < num_pages; page++) {
728 		prlo_acc->prlo_acc_params[page].opa_valid = 0;
729 		prlo_acc->prlo_acc_params[page].rpa_valid = 0;
730 		prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
731 		prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
732 		prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
733 	}
734 
735 	return be16_to_cpu(prlo_acc->payload_len);
736 }
737 
738 u16
739 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
740 		u32 s_id, u16 ox_id, u32 data_format)
741 {
742 	fc_els_req_build(fchs, d_id, s_id, ox_id);
743 
744 	memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
745 
746 	rnid->els_cmd.els_code = FC_ELS_RNID;
747 	rnid->node_id_data_format = data_format;
748 
749 	return sizeof(struct fc_rnid_cmd_s);
750 }
751 
752 u16
753 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
754 		  u32 s_id, __be16 ox_id, u32 data_format,
755 		  struct fc_rnid_common_id_data_s *common_id_data,
756 		  struct fc_rnid_general_topology_data_s *gen_topo_data)
757 {
758 	memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
759 
760 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
761 
762 	rnid_acc->els_cmd.els_code = FC_ELS_ACC;
763 	rnid_acc->node_id_data_format = data_format;
764 	rnid_acc->common_id_data_length =
765 			sizeof(struct fc_rnid_common_id_data_s);
766 	rnid_acc->common_id_data = *common_id_data;
767 
768 	if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
769 		rnid_acc->specific_id_data_length =
770 			sizeof(struct fc_rnid_general_topology_data_s);
771 		rnid_acc->gen_topology_data = *gen_topo_data;
772 		return sizeof(struct fc_rnid_acc_s);
773 	} else {
774 		return sizeof(struct fc_rnid_acc_s) -
775 			sizeof(struct fc_rnid_general_topology_data_s);
776 	}
777 
778 }
779 
780 u16
781 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
782 		u32 s_id, u16 ox_id)
783 {
784 	fc_els_req_build(fchs, d_id, s_id, ox_id);
785 
786 	memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
787 
788 	rpsc->els_cmd.els_code = FC_ELS_RPSC;
789 	return sizeof(struct fc_rpsc_cmd_s);
790 }
791 
792 u16
793 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
794 		u32 s_id, u32 *pid_list, u16 npids)
795 {
796 	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
797 	int i = 0;
798 
799 	fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
800 
801 	memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
802 
803 	rpsc2->els_cmd.els_code = FC_ELS_RPSC;
804 	rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN);
805 	rpsc2->num_pids  = cpu_to_be16(npids);
806 	for (i = 0; i < npids; i++)
807 		rpsc2->pid_list[i].pid = pid_list[i];
808 
809 	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
810 }
811 
812 u16
813 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
814 		u32 d_id, u32 s_id, __be16 ox_id,
815 		  struct fc_rpsc_speed_info_s *oper_speed)
816 {
817 	memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
818 
819 	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
820 
821 	rpsc_acc->command = FC_ELS_ACC;
822 	rpsc_acc->num_entries = cpu_to_be16(1);
823 
824 	rpsc_acc->speed_info[0].port_speed_cap =
825 		cpu_to_be16(oper_speed->port_speed_cap);
826 
827 	rpsc_acc->speed_info[0].port_op_speed =
828 		cpu_to_be16(oper_speed->port_op_speed);
829 
830 	return sizeof(struct fc_rpsc_acc_s);
831 }
832 
833 u16
834 fc_logo_rsp_parse(struct fchs_s *fchs, int len)
835 {
836 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
837 
838 	len = len;
839 	if (els_cmd->els_code != FC_ELS_ACC)
840 		return FC_PARSE_FAILURE;
841 
842 	return FC_PARSE_OK;
843 }
844 
845 u16
846 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
847 	       wwn_t port_name, wwn_t node_name, u16 pdu_size)
848 {
849 	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
850 
851 	memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
852 
853 	pdisc->els_cmd.els_code = FC_ELS_PDISC;
854 	fc_els_req_build(fchs, d_id, s_id, ox_id);
855 
856 	pdisc->csp.rxsz = pdisc->class3.rxsz = cpu_to_be16(pdu_size);
857 	pdisc->port_name = port_name;
858 	pdisc->node_name = node_name;
859 
860 	return sizeof(struct fc_logi_s);
861 }
862 
863 u16
864 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
865 {
866 	struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
867 
868 	if (len < sizeof(struct fc_logi_s))
869 		return FC_PARSE_LEN_INVAL;
870 
871 	if (pdisc->els_cmd.els_code != FC_ELS_ACC)
872 		return FC_PARSE_ACC_INVAL;
873 
874 	if (!wwn_is_equal(pdisc->port_name, port_name))
875 		return FC_PARSE_PWWN_NOT_EQUAL;
876 
877 	if (!pdisc->class3.class_valid)
878 		return FC_PARSE_NWWN_NOT_EQUAL;
879 
880 	if (be16_to_cpu(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
881 		return FC_PARSE_RXSZ_INVAL;
882 
883 	return FC_PARSE_OK;
884 }
885 
886 u16
887 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
888 	      int num_pages)
889 {
890 	struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
891 	int             page;
892 
893 	fc_els_req_build(fchs, d_id, s_id, ox_id);
894 	memset(prlo, 0, (num_pages * 16) + 4);
895 	prlo->command = FC_ELS_PRLO;
896 	prlo->page_len = 0x10;
897 	prlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
898 
899 	for (page = 0; page < num_pages; page++) {
900 		prlo->prlo_params[page].type = FC_TYPE_FCP;
901 		prlo->prlo_params[page].opa_valid = 0;
902 		prlo->prlo_params[page].rpa_valid = 0;
903 		prlo->prlo_params[page].orig_process_assc = 0;
904 		prlo->prlo_params[page].resp_process_assc = 0;
905 	}
906 
907 	return be16_to_cpu(prlo->payload_len);
908 }
909 
910 u16
911 fc_prlo_rsp_parse(struct fchs_s *fchs, int len)
912 {
913 	struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1);
914 	int             num_pages = 0;
915 	int             page = 0;
916 
917 	len = len;
918 
919 	if (prlo->command != FC_ELS_ACC)
920 		return FC_PARSE_FAILURE;
921 
922 	num_pages = ((be16_to_cpu(prlo->payload_len)) - 4) / 16;
923 
924 	for (page = 0; page < num_pages; page++) {
925 		if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP)
926 			return FC_PARSE_FAILURE;
927 
928 		if (prlo->prlo_acc_params[page].opa_valid != 0)
929 			return FC_PARSE_FAILURE;
930 
931 		if (prlo->prlo_acc_params[page].rpa_valid != 0)
932 			return FC_PARSE_FAILURE;
933 
934 		if (prlo->prlo_acc_params[page].orig_process_assc != 0)
935 			return FC_PARSE_FAILURE;
936 
937 		if (prlo->prlo_acc_params[page].resp_process_assc != 0)
938 			return FC_PARSE_FAILURE;
939 	}
940 	return FC_PARSE_OK;
941 
942 }
943 
944 u16
945 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
946 	       int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
947 {
948 	struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
949 	int             page;
950 
951 	fc_els_req_build(fchs, d_id, s_id, ox_id);
952 	memset(tprlo, 0, (num_pages * 16) + 4);
953 	tprlo->command = FC_ELS_TPRLO;
954 	tprlo->page_len = 0x10;
955 	tprlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
956 
957 	for (page = 0; page < num_pages; page++) {
958 		tprlo->tprlo_params[page].type = FC_TYPE_FCP;
959 		tprlo->tprlo_params[page].opa_valid = 0;
960 		tprlo->tprlo_params[page].rpa_valid = 0;
961 		tprlo->tprlo_params[page].orig_process_assc = 0;
962 		tprlo->tprlo_params[page].resp_process_assc = 0;
963 		if (tprlo_type == FC_GLOBAL_LOGO) {
964 			tprlo->tprlo_params[page].global_process_logout = 1;
965 		} else if (tprlo_type == FC_TPR_LOGO) {
966 			tprlo->tprlo_params[page].tpo_nport_valid = 1;
967 			tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
968 		}
969 	}
970 
971 	return be16_to_cpu(tprlo->payload_len);
972 }
973 
974 u16
975 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len)
976 {
977 	struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1);
978 	int             num_pages = 0;
979 	int             page = 0;
980 
981 	len = len;
982 
983 	if (tprlo->command != FC_ELS_ACC)
984 		return FC_PARSE_ACC_INVAL;
985 
986 	num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
987 
988 	for (page = 0; page < num_pages; page++) {
989 		if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP)
990 			return FC_PARSE_NOT_FCP;
991 		if (tprlo->tprlo_acc_params[page].opa_valid != 0)
992 			return FC_PARSE_OPAFLAG_INVAL;
993 		if (tprlo->tprlo_acc_params[page].rpa_valid != 0)
994 			return FC_PARSE_RPAFLAG_INVAL;
995 		if (tprlo->tprlo_acc_params[page].orig_process_assc != 0)
996 			return FC_PARSE_OPA_INVAL;
997 		if (tprlo->tprlo_acc_params[page].resp_process_assc != 0)
998 			return FC_PARSE_RPA_INVAL;
999 	}
1000 	return FC_PARSE_OK;
1001 }
1002 
1003 enum fc_parse_status
1004 fc_rrq_rsp_parse(struct fchs_s *fchs, int len)
1005 {
1006 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
1007 
1008 	len = len;
1009 	if (els_cmd->els_code != FC_ELS_ACC)
1010 		return FC_PARSE_FAILURE;
1011 
1012 	return FC_PARSE_OK;
1013 }
1014 
1015 u16
1016 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
1017 		u32 reason_code, u32 reason_expl)
1018 {
1019 	struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
1020 
1021 	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
1022 
1023 	fchs->cat_info = FC_CAT_BA_RJT;
1024 	ba_rjt->reason_code = reason_code;
1025 	ba_rjt->reason_expl = reason_expl;
1026 	return sizeof(struct fc_ba_rjt_s);
1027 }
1028 
1029 static void
1030 fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
1031 {
1032 	memset(cthdr, 0, sizeof(struct ct_hdr_s));
1033 	cthdr->rev_id = CT_GS3_REVISION;
1034 	cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
1035 	cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
1036 	cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
1037 }
1038 
1039 static void
1040 fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
1041 {
1042 	memset(cthdr, 0, sizeof(struct ct_hdr_s));
1043 	cthdr->rev_id = CT_GS3_REVISION;
1044 	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
1045 	cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
1046 	cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
1047 }
1048 
1049 static void
1050 fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
1051 					 u8 sub_type)
1052 {
1053 	memset(cthdr, 0, sizeof(struct ct_hdr_s));
1054 	cthdr->rev_id = CT_GS3_REVISION;
1055 	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
1056 	cthdr->gs_sub_type = sub_type;
1057 	cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
1058 }
1059 
1060 u16
1061 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1062 	       wwn_t port_name)
1063 {
1064 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1065 	struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
1066 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1067 
1068 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1069 	fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
1070 
1071 	memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
1072 	gidpn->port_name = port_name;
1073 	return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
1074 }
1075 
1076 u16
1077 fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1078 	       u32 port_id)
1079 {
1080 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1081 	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
1082 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1083 
1084 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1085 	fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
1086 
1087 	memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
1088 	gpnid->dap = port_id;
1089 	return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
1090 }
1091 
1092 u16
1093 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1094 	       u32 port_id)
1095 {
1096 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1097 	fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
1098 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1099 
1100 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1101 	fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
1102 
1103 	memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
1104 	gnnid->dap = port_id;
1105 	return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
1106 }
1107 
1108 u16
1109 fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
1110 {
1111 	if (be16_to_cpu(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
1112 		if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
1113 			return FC_PARSE_BUSY;
1114 		else
1115 			return FC_PARSE_FAILURE;
1116 	}
1117 
1118 	return FC_PARSE_OK;
1119 }
1120 
1121 u16
1122 fc_gs_rjt_build(struct fchs_s *fchs,  struct ct_hdr_s *cthdr,
1123 		u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
1124 		u8 reason_code_expl)
1125 {
1126 	fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
1127 
1128 	cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
1129 	cthdr->rev_id = CT_GS3_REVISION;
1130 
1131 	cthdr->reason_code = reason_code;
1132 	cthdr->exp_code    = reason_code_expl;
1133 	return sizeof(struct ct_hdr_s);
1134 }
1135 
1136 u16
1137 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
1138 		u8 set_br_reg, u32 s_id, u16 ox_id)
1139 {
1140 	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
1141 
1142 	fc_els_req_build(fchs, d_id, s_id, ox_id);
1143 
1144 	memset(scr, 0, sizeof(struct fc_scr_s));
1145 	scr->command = FC_ELS_SCR;
1146 	scr->reg_func = FC_SCR_REG_FUNC_FULL;
1147 	if (set_br_reg)
1148 		scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
1149 
1150 	return sizeof(struct fc_scr_s);
1151 }
1152 
1153 u16
1154 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
1155 		u32 s_id, u16 ox_id)
1156 {
1157 	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
1158 	u16        payldlen;
1159 
1160 	fc_els_req_build(fchs, d_id, s_id, ox_id);
1161 	rscn->command = FC_ELS_RSCN;
1162 	rscn->pagelen = sizeof(rscn->event[0]);
1163 
1164 	payldlen = sizeof(u32) + rscn->pagelen;
1165 	rscn->payldlen = cpu_to_be16(payldlen);
1166 
1167 	rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
1168 	rscn->event[0].portid = s_id;
1169 
1170 	return sizeof(struct fc_rscn_pl_s);
1171 }
1172 
1173 u16
1174 fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1175 	       enum bfa_lport_role roles)
1176 {
1177 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1178 	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
1179 	u32        type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
1180 	u8         index;
1181 
1182 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1183 	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
1184 
1185 	memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
1186 
1187 	rftid->dap = s_id;
1188 
1189 	/* By default, FCP FC4 Type is registered */
1190 	index = FC_TYPE_FCP >> 5;
1191 	type_value = 1 << (FC_TYPE_FCP % 32);
1192 	rftid->fc4_type[index] = cpu_to_be32(type_value);
1193 
1194 	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
1195 }
1196 
1197 u16
1198 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1199 		   u8 *fc4_bitmap, u32 bitmap_size)
1200 {
1201 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1202 	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
1203 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1204 
1205 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1206 	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
1207 
1208 	memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
1209 
1210 	rftid->dap = s_id;
1211 	memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
1212 		(bitmap_size < 32 ? bitmap_size : 32));
1213 
1214 	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
1215 }
1216 
1217 u16
1218 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1219 	       u8 fc4_type, u8 fc4_ftrs)
1220 {
1221 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1222 	struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
1223 	u32         d_id = bfa_hton3b(FC_NAME_SERVER);
1224 
1225 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1226 	fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
1227 
1228 	memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
1229 
1230 	rffid->dap	    = s_id;
1231 	rffid->fc4ftr_bits  = fc4_ftrs;
1232 	rffid->fc4_type	    = fc4_type;
1233 
1234 	return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
1235 }
1236 
1237 u16
1238 fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
1239 		u8 *name)
1240 {
1241 
1242 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1243 	struct fcgs_rspnid_req_s *rspnid =
1244 			(struct fcgs_rspnid_req_s *)(cthdr + 1);
1245 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1246 
1247 	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
1248 	fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
1249 
1250 	memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
1251 
1252 	rspnid->dap = s_id;
1253 	rspnid->spn_len = (u8) strlen((char *)name);
1254 	strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len);
1255 
1256 	return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
1257 }
1258 
1259 u16
1260 fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
1261 			wwn_t node_name, u8 *name)
1262 {
1263 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1264 	struct fcgs_rsnn_nn_req_s *rsnn_nn =
1265 		(struct fcgs_rsnn_nn_req_s *) (cthdr + 1);
1266 	u32	d_id = bfa_hton3b(FC_NAME_SERVER);
1267 
1268 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1269 	fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN);
1270 
1271 	memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s));
1272 
1273 	rsnn_nn->node_name = node_name;
1274 	rsnn_nn->snn_len = (u8) strlen((char *)name);
1275 	strncpy((char *)rsnn_nn->snn, (char *)name, rsnn_nn->snn_len);
1276 
1277 	return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s);
1278 }
1279 
1280 u16
1281 fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
1282 {
1283 
1284 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1285 	struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
1286 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1287 
1288 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1289 
1290 	fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
1291 
1292 	memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
1293 	gidft->fc4_type = fc4_type;
1294 	gidft->domain_id = 0;
1295 	gidft->area_id = 0;
1296 
1297 	return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
1298 }
1299 
1300 u16
1301 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
1302 	       wwn_t port_name)
1303 {
1304 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1305 	struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
1306 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1307 
1308 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1309 	fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
1310 
1311 	memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
1312 	rpnid->port_id = port_id;
1313 	rpnid->port_name = port_name;
1314 
1315 	return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
1316 }
1317 
1318 u16
1319 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
1320 	       wwn_t node_name)
1321 {
1322 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1323 	struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
1324 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1325 
1326 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1327 	fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
1328 
1329 	memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
1330 	rnnid->port_id = port_id;
1331 	rnnid->node_name = node_name;
1332 
1333 	return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
1334 }
1335 
1336 u16
1337 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
1338 	       u32 cos)
1339 {
1340 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1341 	struct fcgs_rcsid_req_s *rcsid =
1342 			(struct fcgs_rcsid_req_s *) (cthdr + 1);
1343 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1344 
1345 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1346 	fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
1347 
1348 	memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
1349 	rcsid->port_id = port_id;
1350 	rcsid->cos = cos;
1351 
1352 	return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
1353 }
1354 
1355 u16
1356 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
1357 	       u8 port_type)
1358 {
1359 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1360 	struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
1361 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1362 
1363 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1364 	fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
1365 
1366 	memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
1367 	rptid->port_id = port_id;
1368 	rptid->port_type = port_type;
1369 
1370 	return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
1371 }
1372 
1373 u16
1374 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
1375 {
1376 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1377 	struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
1378 	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
1379 
1380 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1381 	fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
1382 
1383 	memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
1384 	ganxt->port_id = port_id;
1385 
1386 	return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
1387 }
1388 
1389 /*
1390  * Builds fc hdr and ct hdr for FDMI requests.
1391  */
1392 u16
1393 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
1394 		     u16 cmd_code)
1395 {
1396 
1397 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1398 	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
1399 
1400 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1401 	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
1402 
1403 	return sizeof(struct ct_hdr_s);
1404 }
1405 
1406 /*
1407  * Given a FC4 Type, this function returns a fc4 type bitmask
1408  */
1409 void
1410 fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
1411 {
1412 	u8         index;
1413 	__be32       *ptr = (__be32 *) bit_mask;
1414 	u32        type_value;
1415 
1416 	/*
1417 	 * @todo : Check for bitmask size
1418 	 */
1419 
1420 	index = fc4_type >> 5;
1421 	type_value = 1 << (fc4_type % 32);
1422 	ptr[index] = cpu_to_be32(type_value);
1423 
1424 }
1425 
1426 /*
1427  *	GMAL Request
1428  */
1429 u16
1430 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
1431 {
1432 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1433 	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
1434 	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
1435 
1436 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1437 	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
1438 			CT_GSSUBTYPE_CFGSERVER);
1439 
1440 	memset(gmal, 0, sizeof(fcgs_gmal_req_t));
1441 	gmal->wwn = wwn;
1442 
1443 	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
1444 }
1445 
1446 /*
1447  * GFN (Get Fabric Name) Request
1448  */
1449 u16
1450 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
1451 {
1452 	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
1453 	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
1454 	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
1455 
1456 	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
1457 	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
1458 			CT_GSSUBTYPE_CFGSERVER);
1459 
1460 	memset(gfn, 0, sizeof(fcgs_gfn_req_t));
1461 	gfn->wwn = wwn;
1462 
1463 	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
1464 }
1465