File Index
Files and directories
Sign in
FILE

bfa_fcbuild.c

File preview with syntax highlighting.

linux-6.19.14/drivers/scsi/bfa/bfa_fcbuild.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
  4 * Copyright (c) 2014- QLogic Corporation.
  5 * All rights reserved
  6 * www.qlogic.com
  7 *
  8 * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
  9 */
 10/*
 11 * fcbuild.c - FC link service frame building and parsing routines
 12 */
 13
 14#include "bfad_drv.h"
 15#include "bfa_fcbuild.h"
 16
 17/*
 18 * static build functions
 19 */
 20static void     fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
 21				 __be16 ox_id);
 22static void     fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
 23				 __be16 ox_id);
 24static struct fchs_s fc_els_req_tmpl;
 25static struct fchs_s fc_els_rsp_tmpl;
 26static struct fchs_s fc_bls_req_tmpl;
 27static struct fchs_s fc_bls_rsp_tmpl;
 28static struct fc_ba_acc_s ba_acc_tmpl;
 29static struct fc_logi_s plogi_tmpl;
 30static struct fc_prli_s prli_tmpl;
 31static struct fc_rrq_s rrq_tmpl;
 32static struct fchs_s fcp_fchs_tmpl;
 33
 34void
 35fcbuild_init(void)
 36{
 37	/*
 38	 * fc_els_req_tmpl
 39	 */
 40	fc_els_req_tmpl.routing = FC_RTG_EXT_LINK;
 41	fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST;
 42	fc_els_req_tmpl.type = FC_TYPE_ELS;
 43	fc_els_req_tmpl.f_ctl =
 44		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
 45			      FCTL_SI_XFER);
 46	fc_els_req_tmpl.rx_id = FC_RXID_ANY;
 47
 48	/*
 49	 * fc_els_rsp_tmpl
 50	 */
 51	fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK;
 52	fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY;
 53	fc_els_rsp_tmpl.type = FC_TYPE_ELS;
 54	fc_els_rsp_tmpl.f_ctl =
 55		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
 56			      FCTL_END_SEQ | FCTL_SI_XFER);
 57	fc_els_rsp_tmpl.rx_id = FC_RXID_ANY;
 58
 59	/*
 60	 * fc_bls_req_tmpl
 61	 */
 62	fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK;
 63	fc_bls_req_tmpl.type = FC_TYPE_BLS;
 64	fc_bls_req_tmpl.f_ctl = bfa_hton3b(FCTL_END_SEQ | FCTL_SI_XFER);
 65	fc_bls_req_tmpl.rx_id = FC_RXID_ANY;
 66
 67	/*
 68	 * fc_bls_rsp_tmpl
 69	 */
 70	fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK;
 71	fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC;
 72	fc_bls_rsp_tmpl.type = FC_TYPE_BLS;
 73	fc_bls_rsp_tmpl.f_ctl =
 74		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
 75			      FCTL_END_SEQ | FCTL_SI_XFER);
 76	fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY;
 77
 78	/*
 79	 * ba_acc_tmpl
 80	 */
 81	ba_acc_tmpl.seq_id_valid = 0;
 82	ba_acc_tmpl.low_seq_cnt = 0;
 83	ba_acc_tmpl.high_seq_cnt = 0xFFFF;
 84
 85	/*
 86	 * plogi_tmpl
 87	 */
 88	plogi_tmpl.csp.verhi = FC_PH_VER_PH_3;
 89	plogi_tmpl.csp.verlo = FC_PH_VER_4_3;
 90	plogi_tmpl.csp.ciro = 0x1;
 91	plogi_tmpl.csp.cisc = 0x0;
 92	plogi_tmpl.csp.altbbcred = 0x0;
 93	plogi_tmpl.csp.conseq = cpu_to_be16(0x00FF);
 94	plogi_tmpl.csp.ro_bitmap = cpu_to_be16(0x0002);
 95	plogi_tmpl.csp.e_d_tov = cpu_to_be32(2000);
 96
 97	plogi_tmpl.class3.class_valid = 1;
 98	plogi_tmpl.class3.sequential = 1;
 99	plogi_tmpl.class3.conseq = 0xFF;
100	plogi_tmpl.class3.ospx = 1;
101
102	/*
103	 * prli_tmpl
104	 */
105	prli_tmpl.command = FC_ELS_PRLI;
106	prli_tmpl.pglen = 0x10;
107	prli_tmpl.pagebytes = cpu_to_be16(0x0014);
108	prli_tmpl.parampage.type = FC_TYPE_FCP;
109	prli_tmpl.parampage.imagepair = 1;
110	prli_tmpl.parampage.servparams.rxrdisab = 1;
111
112	/*
113	 * rrq_tmpl
114	 */
115	rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ;
116
117	/*
118	 * fcp_struct fchs_s mpl
119	 */
120	fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA;
121	fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD;
122	fcp_fchs_tmpl.type = FC_TYPE_FCP;
123	fcp_fchs_tmpl.f_ctl =
124		bfa_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER);
125	fcp_fchs_tmpl.seq_id = 1;
126	fcp_fchs_tmpl.rx_id = FC_RXID_ANY;
127}
128
129static void
130fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u32 ox_id)
131{
132	memset(fchs, 0, sizeof(struct fchs_s));
133
134	fchs->routing = FC_RTG_FC4_DEV_DATA;
135	fchs->cat_info = FC_CAT_UNSOLICIT_CTRL;
136	fchs->type = FC_TYPE_SERVICES;
137	fchs->f_ctl =
138		bfa_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ |
139			      FCTL_SI_XFER);
140	fchs->rx_id = FC_RXID_ANY;
141	fchs->d_id = (d_id);
142	fchs->s_id = (s_id);
143	fchs->ox_id = cpu_to_be16(ox_id);
144
145	/*
146	 * @todo no need to set ox_id for request
147	 *       no need to set rx_id for response
148	 */
149}
150
151static void
152fc_gsresp_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
153{
154	memset(fchs, 0, sizeof(struct fchs_s));
155
156	fchs->routing = FC_RTG_FC4_DEV_DATA;
157	fchs->cat_info = FC_CAT_SOLICIT_CTRL;
158	fchs->type = FC_TYPE_SERVICES;
159	fchs->f_ctl =
160		bfa_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH |
161			   FCTL_END_SEQ | FCTL_SI_XFER);
162	fchs->d_id = d_id;
163	fchs->s_id = s_id;
164	fchs->ox_id = ox_id;
165}
166
167void
168fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
169{
170	memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s));
171	fchs->d_id = (d_id);
172	fchs->s_id = (s_id);
173	fchs->ox_id = cpu_to_be16(ox_id);
174}
175
176static void
177fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
178{
179	memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s));
180	fchs->d_id = d_id;
181	fchs->s_id = s_id;
182	fchs->ox_id = ox_id;
183}
184
185static void
186fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id)
187{
188	memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s));
189	fchs->d_id = d_id;
190	fchs->s_id = s_id;
191	fchs->ox_id = ox_id;
192}
193
194static          u16
195fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
196		 __be16 ox_id, wwn_t port_name, wwn_t node_name,
197		 u16 pdu_size, u16 bb_cr, u8 els_code)
198{
199	struct fc_logi_s *plogi = (struct fc_logi_s *) (pld);
200
201	memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s));
202
203	/* For FC AL bb_cr is 0 and altbbcred is 1 */
204	if (!bb_cr)
205		plogi->csp.altbbcred = 1;
206
207	plogi->els_cmd.els_code = els_code;
208	if (els_code == FC_ELS_PLOGI)
209		fc_els_req_build(fchs, d_id, s_id, ox_id);
210	else
211		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
212
213	plogi->csp.rxsz = plogi->class3.rxsz = cpu_to_be16(pdu_size);
214	plogi->csp.bbcred  = cpu_to_be16(bb_cr);
215
216	memcpy(&plogi->port_name, &port_name, sizeof(wwn_t));
217	memcpy(&plogi->node_name, &node_name, sizeof(wwn_t));
218
219	return sizeof(struct fc_logi_s);
220}
221
222u16
223fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
224		   __be16 ox_id, wwn_t port_name, wwn_t node_name,
225		   u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
226{
227	u32        d_id = 0;
228	u16	   bbscn_rxsz = (bb_scn << 12) | pdu_size;
229
230	memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
231	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
232
233	flogi->els_cmd.els_code = FC_ELS_ACC;
234	flogi->class3.rxsz = cpu_to_be16(pdu_size);
235	flogi->csp.rxsz  = cpu_to_be16(bbscn_rxsz);	/* bb_scn/rxsz */
236	flogi->port_name = port_name;
237	flogi->node_name = node_name;
238
239	flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
240
241	return sizeof(struct fc_logi_s);
242}
243
244u16
245fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
246	       u16 ox_id, wwn_t port_name, wwn_t node_name,
247	       u16 pdu_size, u16 bb_cr)
248{
249	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
250				node_name, pdu_size, bb_cr, FC_ELS_PLOGI);
251}
252
253u16
254fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
255		   u16 ox_id, wwn_t port_name, wwn_t node_name,
256		   u16 pdu_size, u16 bb_cr)
257{
258	return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name,
259				node_name, pdu_size, bb_cr, FC_ELS_ACC);
260}
261
262enum fc_parse_status
263fc_plogi_parse(struct fchs_s *fchs)
264{
265	struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
266
267	if (plogi->class3.class_valid != 1)
268		return FC_PARSE_FAILURE;
269
270	if ((be16_to_cpu(plogi->class3.rxsz) < FC_MIN_PDUSZ)
271	    || (be16_to_cpu(plogi->class3.rxsz) > FC_MAX_PDUSZ)
272	    || (plogi->class3.rxsz == 0))
273		return FC_PARSE_FAILURE;
274
275	return FC_PARSE_OK;
276}
277
278u16
279fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
280	      u16 ox_id)
281{
282	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
283
284	fc_els_req_build(fchs, d_id, s_id, ox_id);
285	memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
286
287	prli->command = FC_ELS_PRLI;
288	prli->parampage.servparams.initiator     = 1;
289	prli->parampage.servparams.retry         = 1;
290	prli->parampage.servparams.rec_support   = 1;
291	prli->parampage.servparams.task_retry_id = 0;
292	prli->parampage.servparams.confirm       = 1;
293
294	return sizeof(struct fc_prli_s);
295}
296
297u16
298fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
299		  __be16 ox_id, enum bfa_lport_role role)
300{
301	struct fc_prli_s *prli = (struct fc_prli_s *) (pld);
302
303	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
304	memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s));
305
306	prli->command = FC_ELS_ACC;
307
308	prli->parampage.servparams.initiator = 1;
309
310	prli->parampage.rspcode = FC_PRLI_ACC_XQTD;
311
312	return sizeof(struct fc_prli_s);
313}
314
315enum fc_parse_status
316fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
317{
318	if (len < sizeof(struct fc_prli_s))
319		return FC_PARSE_FAILURE;
320
321	if (prli->command != FC_ELS_ACC)
322		return FC_PARSE_FAILURE;
323
324	if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD)
325	    && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG))
326		return FC_PARSE_FAILURE;
327
328	if (prli->parampage.servparams.target != 1)
329		return FC_PARSE_FAILURE;
330
331	return FC_PARSE_OK;
332}
333
334u16
335fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
336	      u16 ox_id, wwn_t port_name)
337{
338	fc_els_req_build(fchs, d_id, s_id, ox_id);
339
340	memset(logo, '\0', sizeof(struct fc_logo_s));
341	logo->els_cmd.els_code = FC_ELS_LOGO;
342	logo->nport_id = (s_id);
343	logo->orig_port_name = port_name;
344
345	return sizeof(struct fc_logo_s);
346}
347
348static u16
349fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
350		 u32 s_id, __be16 ox_id, wwn_t port_name,
351		 wwn_t node_name, u8 els_code)
352{
353	memset(adisc, '\0', sizeof(struct fc_adisc_s));
354
355	adisc->els_cmd.els_code = els_code;
356
357	if (els_code == FC_ELS_ADISC)
358		fc_els_req_build(fchs, d_id, s_id, ox_id);
359	else
360		fc_els_rsp_build(fchs, d_id, s_id, ox_id);
361
362	adisc->orig_HA = 0;
363	adisc->orig_port_name = port_name;
364	adisc->orig_node_name = node_name;
365	adisc->nport_id = (s_id);
366
367	return sizeof(struct fc_adisc_s);
368}
369
370u16
371fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
372		u32 s_id, __be16 ox_id, wwn_t port_name, wwn_t node_name)
373{
374	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
375				node_name, FC_ELS_ADISC);
376}
377
378u16
379fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id,
380		   u32 s_id, __be16 ox_id, wwn_t port_name,
381		   wwn_t node_name)
382{
383	return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name,
384				node_name, FC_ELS_ACC);
385}
386
387enum fc_parse_status
388fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
389				 wwn_t node_name)
390{
391
392	if (len < sizeof(struct fc_adisc_s))
393		return FC_PARSE_FAILURE;
394
395	if (adisc->els_cmd.els_code != FC_ELS_ACC)
396		return FC_PARSE_FAILURE;
397
398	if (!wwn_is_equal(adisc->orig_port_name, port_name))
399		return FC_PARSE_FAILURE;
400
401	return FC_PARSE_OK;
402}
403
404u16
405fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
406		  __be16 ox_id)
407{
408	struct fc_els_cmd_s *acc = pld;
409
410	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
411
412	memset(acc, 0, sizeof(struct fc_els_cmd_s));
413	acc->els_code = FC_ELS_ACC;
414
415	return sizeof(struct fc_els_cmd_s);
416}
417
418u16
419fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id,
420		u32 s_id, __be16 ox_id, u8 reason_code,
421		u8 reason_code_expl)
422{
423	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
424	memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s));
425
426	ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT;
427	ls_rjt->reason_code = reason_code;
428	ls_rjt->reason_code_expl = reason_code_expl;
429	ls_rjt->vendor_unique = 0x00;
430
431	return sizeof(struct fc_ls_rjt_s);
432}
433
434u16
435fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
436		u32 s_id, __be16 ox_id, u16 rx_id)
437{
438	fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
439
440	memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s));
441
442	fchs->rx_id = rx_id;
443
444	ba_acc->ox_id = fchs->ox_id;
445	ba_acc->rx_id = fchs->rx_id;
446
447	return sizeof(struct fc_ba_acc_s);
448}
449
450u16
451fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, u32 d_id,
452		u32 s_id, __be16 ox_id)
453{
454	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
455	memset(els_cmd, 0, sizeof(struct fc_els_cmd_s));
456	els_cmd->els_code = FC_ELS_ACC;
457
458	return sizeof(struct fc_els_cmd_s);
459}
460
461int
462fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
463{
464	int             num_pages = 0;
465	struct fc_prlo_s *prlo;
466	struct fc_tprlo_s *tprlo;
467
468	if (els_code == FC_ELS_PRLO) {
469		prlo = (struct fc_prlo_s *) (fc_frame + 1);
470		num_pages = (be16_to_cpu(prlo->payload_len) - 4) / 16;
471	} else {
472		tprlo = (struct fc_tprlo_s *) (fc_frame + 1);
473		num_pages = (be16_to_cpu(tprlo->payload_len) - 4) / 16;
474	}
475	return num_pages;
476}
477
478u16
479fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
480		  u32 s_id, __be16 ox_id, int num_pages)
481{
482	int             page;
483
484	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
485
486	memset(prlo_acc, 0, (num_pages * 16) + 4);
487	prlo_acc->command = FC_ELS_ACC;
488	prlo_acc->page_len = 0x10;
489	prlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
490
491	for (page = 0; page < num_pages; page++) {
492		prlo_acc->prlo_acc_params[page].opa_valid = 0;
493		prlo_acc->prlo_acc_params[page].rpa_valid = 0;
494		prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
495		prlo_acc->prlo_acc_params[page].orig_process_assc = 0;
496		prlo_acc->prlo_acc_params[page].resp_process_assc = 0;
497	}
498
499	return be16_to_cpu(prlo_acc->payload_len);
500}
501
502u16
503fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
504		  u32 s_id, __be16 ox_id, u32 data_format,
505		  struct fc_rnid_common_id_data_s *common_id_data,
506		  struct fc_rnid_general_topology_data_s *gen_topo_data)
507{
508	memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s));
509
510	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
511
512	rnid_acc->els_cmd.els_code = FC_ELS_ACC;
513	rnid_acc->node_id_data_format = data_format;
514	rnid_acc->common_id_data_length =
515			sizeof(struct fc_rnid_common_id_data_s);
516	rnid_acc->common_id_data = *common_id_data;
517
518	if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
519		rnid_acc->specific_id_data_length =
520			sizeof(struct fc_rnid_general_topology_data_s);
521		rnid_acc->gen_topology_data = *gen_topo_data;
522		return sizeof(struct fc_rnid_acc_s);
523	} else {
524		return sizeof(struct fc_rnid_acc_s) -
525			sizeof(struct fc_rnid_general_topology_data_s);
526	}
527
528}
529
530u16
531fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
532		u32 s_id, u32 *pid_list, u16 npids)
533{
534	u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_hton3b(d_id));
535	int i = 0;
536
537	fc_els_req_build(fchs, bfa_hton3b(dctlr_id), s_id, 0);
538
539	memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s));
540
541	rpsc2->els_cmd.els_code = FC_ELS_RPSC;
542	rpsc2->token = cpu_to_be32(FC_BRCD_TOKEN);
543	rpsc2->num_pids  = cpu_to_be16(npids);
544	for (i = 0; i < npids; i++)
545		rpsc2->pid_list[i].pid = pid_list[i];
546
547	return sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * (sizeof(u32)));
548}
549
550u16
551fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
552		u32 d_id, u32 s_id, __be16 ox_id,
553		  struct fc_rpsc_speed_info_s *oper_speed)
554{
555	memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s));
556
557	fc_els_rsp_build(fchs, d_id, s_id, ox_id);
558
559	rpsc_acc->command = FC_ELS_ACC;
560	rpsc_acc->num_entries = cpu_to_be16(1);
561
562	rpsc_acc->speed_info[0].port_speed_cap =
563		cpu_to_be16(oper_speed->port_speed_cap);
564
565	rpsc_acc->speed_info[0].port_op_speed =
566		cpu_to_be16(oper_speed->port_op_speed);
567
568	return sizeof(struct fc_rpsc_acc_s);
569}
570
571static void
572fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
573{
574	memset(cthdr, 0, sizeof(struct ct_hdr_s));
575	cthdr->rev_id = CT_GS3_REVISION;
576	cthdr->gs_type = CT_GSTYPE_DIRSERVICE;
577	cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER;
578	cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
579}
580
581static void
582fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
583{
584	memset(cthdr, 0, sizeof(struct ct_hdr_s));
585	cthdr->rev_id = CT_GS3_REVISION;
586	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
587	cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER;
588	cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
589}
590
591static void
592fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code,
593					 u8 sub_type)
594{
595	memset(cthdr, 0, sizeof(struct ct_hdr_s));
596	cthdr->rev_id = CT_GS3_REVISION;
597	cthdr->gs_type = CT_GSTYPE_MGMTSERVICE;
598	cthdr->gs_sub_type = sub_type;
599	cthdr->cmd_rsp_code = cpu_to_be16(cmd_code);
600}
601
602u16
603fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
604	       wwn_t port_name)
605{
606	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
607	struct fcgs_gidpn_req_s *gidpn = (struct fcgs_gidpn_req_s *)(cthdr + 1);
608	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
609
610	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
611	fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN);
612
613	memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s));
614	gidpn->port_name = port_name;
615	return sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s);
616}
617
618u16
619fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
620	       u32 port_id)
621{
622	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
623	fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1);
624	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
625
626	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
627	fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID);
628
629	memset(gpnid, 0, sizeof(fcgs_gpnid_req_t));
630	gpnid->dap = port_id;
631	return sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s);
632}
633
634u16
635fc_gs_rjt_build(struct fchs_s *fchs,  struct ct_hdr_s *cthdr,
636		u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
637		u8 reason_code_expl)
638{
639	fc_gsresp_fchdr_build(fchs, d_id, s_id, ox_id);
640
641	cthdr->cmd_rsp_code = cpu_to_be16(CT_RSP_REJECT);
642	cthdr->rev_id = CT_GS3_REVISION;
643
644	cthdr->reason_code = reason_code;
645	cthdr->exp_code    = reason_code_expl;
646	return sizeof(struct ct_hdr_s);
647}
648
649u16
650fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
651		u8 set_br_reg, u32 s_id, u16 ox_id)
652{
653	u32        d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
654
655	fc_els_req_build(fchs, d_id, s_id, ox_id);
656
657	memset(scr, 0, sizeof(struct fc_scr_s));
658	scr->command = FC_ELS_SCR;
659	scr->reg_func = FC_SCR_REG_FUNC_FULL;
660	if (set_br_reg)
661		scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE;
662
663	return sizeof(struct fc_scr_s);
664}
665
666u16
667fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
668	       enum bfa_lport_role roles)
669{
670	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
671	struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
672	u32        type_value, d_id = bfa_hton3b(FC_NAME_SERVER);
673	u8         index;
674
675	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
676	fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
677
678	memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
679
680	rftid->dap = s_id;
681
682	/* By default, FCP FC4 Type is registered */
683	index = FC_TYPE_FCP >> 5;
684	type_value = 1 << (FC_TYPE_FCP % 32);
685	rftid->fc4_type[index] = cpu_to_be32(type_value);
686
687	return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
688}
689
690u16
691fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
692	       u8 fc4_type, u8 fc4_ftrs)
693{
694	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
695	struct fcgs_rffid_req_s *rffid = (struct fcgs_rffid_req_s *)(cthdr + 1);
696	u32         d_id = bfa_hton3b(FC_NAME_SERVER);
697
698	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
699	fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID);
700
701	memset(rffid, 0, sizeof(struct fcgs_rffid_req_s));
702
703	rffid->dap	    = s_id;
704	rffid->fc4ftr_bits  = fc4_ftrs;
705	rffid->fc4_type	    = fc4_type;
706
707	return sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s);
708}
709
710u16
711fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
712		u8 *name)
713{
714
715	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
716	struct fcgs_rspnid_req_s *rspnid =
717			(struct fcgs_rspnid_req_s *)(cthdr + 1);
718	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
719
720	fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
721	fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID);
722
723	memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s));
724
725	rspnid->dap = s_id;
726	strscpy(rspnid->spn, name, sizeof(rspnid->spn));
727	rspnid->spn_len = (u8) strlen(rspnid->spn);
728
729	return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s);
730}
731
732u16
733fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id,
734			wwn_t node_name, u8 *name)
735{
736	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
737	struct fcgs_rsnn_nn_req_s *rsnn_nn =
738		(struct fcgs_rsnn_nn_req_s *) (cthdr + 1);
739	u32	d_id = bfa_hton3b(FC_NAME_SERVER);
740
741	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
742	fc_gs_cthdr_build(cthdr, s_id, GS_RSNN_NN);
743
744	memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s));
745
746	rsnn_nn->node_name = node_name;
747	strscpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn));
748	rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn);
749
750	return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s);
751}
752
753u16
754fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
755{
756
757	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
758	struct fcgs_gidft_req_s *gidft = (struct fcgs_gidft_req_s *)(cthdr + 1);
759	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
760
761	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
762
763	fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT);
764
765	memset(gidft, 0, sizeof(struct fcgs_gidft_req_s));
766	gidft->fc4_type = fc4_type;
767	gidft->domain_id = 0;
768	gidft->area_id = 0;
769
770	return sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s);
771}
772
773u16
774fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
775	       wwn_t node_name)
776{
777	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
778	struct fcgs_rnnid_req_s *rnnid = (struct fcgs_rnnid_req_s *)(cthdr + 1);
779	u32        d_id = bfa_hton3b(FC_NAME_SERVER);
780
781	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
782	fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID);
783
784	memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s));
785	rnnid->port_id = port_id;
786	rnnid->node_name = node_name;
787
788	return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
789}
790
791/*
792 * Builds fc hdr and ct hdr for FDMI requests.
793 */
794u16
795fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id,
796		     u16 cmd_code)
797{
798
799	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
800	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
801
802	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
803	fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code);
804
805	return sizeof(struct ct_hdr_s);
806}
807
808/*
809 * Given a FC4 Type, this function returns a fc4 type bitmask
810 */
811void
812fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask)
813{
814	u8         index;
815	__be32       *ptr = (__be32 *) bit_mask;
816	u32        type_value;
817
818	/*
819	 * @todo : Check for bitmask size
820	 */
821
822	index = fc4_type >> 5;
823	type_value = 1 << (fc4_type % 32);
824	ptr[index] = cpu_to_be32(type_value);
825
826}
827
828/*
829 *	GMAL Request
830 */
831u16
832fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
833{
834	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
835	fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1);
836	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
837
838	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
839	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD,
840			CT_GSSUBTYPE_CFGSERVER);
841
842	memset(gmal, 0, sizeof(fcgs_gmal_req_t));
843	gmal->wwn = wwn;
844
845	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t);
846}
847
848/*
849 * GFN (Get Fabric Name) Request
850 */
851u16
852fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn)
853{
854	struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
855	fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1);
856	u32        d_id = bfa_hton3b(FC_MGMT_SERVER);
857
858	fc_gs_fchdr_build(fchs, d_id, s_id, 0);
859	fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD,
860			CT_GSSUBTYPE_CFGSERVER);
861
862	memset(gfn, 0, sizeof(fcgs_gfn_req_t));
863	gfn->wwn = wwn;
864
865	return sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t);
866}
~/ Read-only file preview.