1 /*
2  * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
3  * All rights reserved
4  * www.brocade.com
5  *
6  * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License (GPL) Version 2 as
10  * published by the Free Software Foundation
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  */
17 
18 #include "bfad_drv.h"
19 #include "bfa_fcs.h"
20 #include "bfa_fcbuild.h"
21 #include "bfa_fc.h"
22 
23 BFA_TRC_FILE(FCS, PORT);
24 
25 static void     bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port,
26 					 struct fchs_s *rx_fchs, u8 reason_code,
27 					 u8 reason_code_expl);
28 static void     bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
29 			struct fchs_s *rx_fchs, struct fc_logi_s *plogi);
30 static void     bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port);
31 static void     bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port);
32 static void     bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port);
33 static void     bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port);
34 static void     bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port);
35 static void     bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port);
36 static void     bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port,
37 			struct fchs_s *rx_fchs,
38 			struct fc_echo_s *echo, u16 len);
39 static void     bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port,
40 			struct fchs_s *rx_fchs,
41 			struct fc_rnid_cmd_s *rnid, u16 len);
42 static void     bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
43 			struct fc_rnid_general_topology_data_s *gen_topo_data);
44 
45 static void	bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port);
46 static void	bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port);
47 static void	bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port);
48 
49 static void	bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port);
50 static void	bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port);
51 static void	bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port);
52 
53 static struct {
54 	void		(*init) (struct bfa_fcs_lport_s *port);
55 	void		(*online) (struct bfa_fcs_lport_s *port);
56 	void		(*offline) (struct bfa_fcs_lport_s *port);
57 } __port_action[] = {
58 	{
59 	bfa_fcs_lport_unknown_init, bfa_fcs_lport_unknown_online,
60 			bfa_fcs_lport_unknown_offline}, {
61 	bfa_fcs_lport_fab_init, bfa_fcs_lport_fab_online,
62 			bfa_fcs_lport_fab_offline}, {
63 	bfa_fcs_lport_n2n_init, bfa_fcs_lport_n2n_online,
64 			bfa_fcs_lport_n2n_offline},
65 	};
66 
67 /*
68  *  fcs_port_sm FCS logical port state machine
69  */
70 
71 enum bfa_fcs_lport_event {
72 	BFA_FCS_PORT_SM_CREATE = 1,
73 	BFA_FCS_PORT_SM_ONLINE = 2,
74 	BFA_FCS_PORT_SM_OFFLINE = 3,
75 	BFA_FCS_PORT_SM_DELETE = 4,
76 	BFA_FCS_PORT_SM_DELRPORT = 5,
77 };
78 
79 static void     bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s *port,
80 					enum bfa_fcs_lport_event event);
81 static void     bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
82 					enum bfa_fcs_lport_event event);
83 static void     bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s *port,
84 					enum bfa_fcs_lport_event event);
85 static void     bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s *port,
86 					enum bfa_fcs_lport_event event);
87 static void     bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s *port,
88 					enum bfa_fcs_lport_event event);
89 
90 static void
bfa_fcs_lport_sm_uninit(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)91 bfa_fcs_lport_sm_uninit(
92 	struct bfa_fcs_lport_s *port,
93 	enum bfa_fcs_lport_event event)
94 {
95 	bfa_trc(port->fcs, port->port_cfg.pwwn);
96 	bfa_trc(port->fcs, event);
97 
98 	switch (event) {
99 	case BFA_FCS_PORT_SM_CREATE:
100 		bfa_sm_set_state(port, bfa_fcs_lport_sm_init);
101 		break;
102 
103 	default:
104 		bfa_sm_fault(port->fcs, event);
105 	}
106 }
107 
108 static void
bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)109 bfa_fcs_lport_sm_init(struct bfa_fcs_lport_s *port,
110 			enum bfa_fcs_lport_event event)
111 {
112 	bfa_trc(port->fcs, port->port_cfg.pwwn);
113 	bfa_trc(port->fcs, event);
114 
115 	switch (event) {
116 	case BFA_FCS_PORT_SM_ONLINE:
117 		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
118 		bfa_fcs_lport_online_actions(port);
119 		break;
120 
121 	case BFA_FCS_PORT_SM_DELETE:
122 		bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
123 		bfa_fcs_lport_deleted(port);
124 		break;
125 
126 	case BFA_FCS_PORT_SM_OFFLINE:
127 		break;
128 
129 	default:
130 		bfa_sm_fault(port->fcs, event);
131 	}
132 }
133 
134 static void
bfa_fcs_lport_sm_online(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)135 bfa_fcs_lport_sm_online(
136 	struct bfa_fcs_lport_s *port,
137 	enum bfa_fcs_lport_event event)
138 {
139 	struct bfa_fcs_rport_s *rport;
140 	struct list_head		*qe, *qen;
141 
142 	bfa_trc(port->fcs, port->port_cfg.pwwn);
143 	bfa_trc(port->fcs, event);
144 
145 	switch (event) {
146 	case BFA_FCS_PORT_SM_OFFLINE:
147 		bfa_sm_set_state(port, bfa_fcs_lport_sm_offline);
148 		bfa_fcs_lport_offline_actions(port);
149 		break;
150 
151 	case BFA_FCS_PORT_SM_DELETE:
152 
153 		__port_action[port->fabric->fab_type].offline(port);
154 
155 		if (port->num_rports == 0) {
156 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
157 			bfa_fcs_lport_deleted(port);
158 		} else {
159 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
160 			list_for_each_safe(qe, qen, &port->rport_q) {
161 				rport = (struct bfa_fcs_rport_s *) qe;
162 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
163 			}
164 		}
165 		break;
166 
167 	case BFA_FCS_PORT_SM_DELRPORT:
168 		break;
169 
170 	default:
171 		bfa_sm_fault(port->fcs, event);
172 	}
173 }
174 
175 static void
bfa_fcs_lport_sm_offline(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)176 bfa_fcs_lport_sm_offline(
177 	struct bfa_fcs_lport_s *port,
178 	enum bfa_fcs_lport_event event)
179 {
180 	struct bfa_fcs_rport_s *rport;
181 	struct list_head		*qe, *qen;
182 
183 	bfa_trc(port->fcs, port->port_cfg.pwwn);
184 	bfa_trc(port->fcs, event);
185 
186 	switch (event) {
187 	case BFA_FCS_PORT_SM_ONLINE:
188 		bfa_sm_set_state(port, bfa_fcs_lport_sm_online);
189 		bfa_fcs_lport_online_actions(port);
190 		break;
191 
192 	case BFA_FCS_PORT_SM_DELETE:
193 		if (port->num_rports == 0) {
194 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
195 			bfa_fcs_lport_deleted(port);
196 		} else {
197 			bfa_sm_set_state(port, bfa_fcs_lport_sm_deleting);
198 			list_for_each_safe(qe, qen, &port->rport_q) {
199 				rport = (struct bfa_fcs_rport_s *) qe;
200 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
201 			}
202 		}
203 		break;
204 
205 	case BFA_FCS_PORT_SM_DELRPORT:
206 	case BFA_FCS_PORT_SM_OFFLINE:
207 		break;
208 
209 	default:
210 		bfa_sm_fault(port->fcs, event);
211 	}
212 }
213 
214 static void
bfa_fcs_lport_sm_deleting(struct bfa_fcs_lport_s * port,enum bfa_fcs_lport_event event)215 bfa_fcs_lport_sm_deleting(
216 	struct bfa_fcs_lport_s *port,
217 	enum bfa_fcs_lport_event event)
218 {
219 	bfa_trc(port->fcs, port->port_cfg.pwwn);
220 	bfa_trc(port->fcs, event);
221 
222 	switch (event) {
223 	case BFA_FCS_PORT_SM_DELRPORT:
224 		if (port->num_rports == 0) {
225 			bfa_sm_set_state(port, bfa_fcs_lport_sm_uninit);
226 			bfa_fcs_lport_deleted(port);
227 		}
228 		break;
229 
230 	default:
231 		bfa_sm_fault(port->fcs, event);
232 	}
233 }
234 
235 /*
236  *  fcs_port_pvt
237  */
238 
239 /*
240  * Send a LS reject
241  */
242 static void
bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,u8 reason_code,u8 reason_code_expl)243 bfa_fcs_lport_send_ls_rjt(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
244 			 u8 reason_code, u8 reason_code_expl)
245 {
246 	struct fchs_s	fchs;
247 	struct bfa_fcxp_s *fcxp;
248 	struct bfa_rport_s *bfa_rport = NULL;
249 	int		len;
250 
251 	bfa_trc(port->fcs, rx_fchs->d_id);
252 	bfa_trc(port->fcs, rx_fchs->s_id);
253 
254 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
255 	if (!fcxp)
256 		return;
257 
258 	len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
259 			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
260 			      rx_fchs->ox_id, reason_code, reason_code_expl);
261 
262 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
263 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
264 			  FC_MAX_PDUSZ, 0);
265 }
266 
267 /*
268  * Process incoming plogi from a remote port.
269  */
270 static void
bfa_fcs_lport_plogi(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_logi_s * plogi)271 bfa_fcs_lport_plogi(struct bfa_fcs_lport_s *port,
272 		struct fchs_s *rx_fchs, struct fc_logi_s *plogi)
273 {
274 	struct bfa_fcs_rport_s *rport;
275 
276 	bfa_trc(port->fcs, rx_fchs->d_id);
277 	bfa_trc(port->fcs, rx_fchs->s_id);
278 
279 	/*
280 	 * If min cfg mode is enabled, drop any incoming PLOGIs
281 	 */
282 	if (__fcs_min_cfg(port->fcs)) {
283 		bfa_trc(port->fcs, rx_fchs->s_id);
284 		return;
285 	}
286 
287 	if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) {
288 		bfa_trc(port->fcs, rx_fchs->s_id);
289 		/*
290 		 * send a LS reject
291 		 */
292 		bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
293 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
294 					FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS);
295 		return;
296 	}
297 
298 	/*
299 	 * Direct Attach P2P mode : verify address assigned by the r-port.
300 	 */
301 	if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
302 		(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
303 			   (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
304 		if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) {
305 			/* Address assigned to us cannot be a WKA */
306 			bfa_fcs_lport_send_ls_rjt(port, rx_fchs,
307 					FC_LS_RJT_RSN_PROTOCOL_ERROR,
308 					FC_LS_RJT_EXP_INVALID_NPORT_ID);
309 			return;
310 		}
311 		port->pid  = rx_fchs->d_id;
312 		bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
313 	}
314 
315 	/*
316 	 * First, check if we know the device by pwwn.
317 	 */
318 	rport = bfa_fcs_lport_get_rport_by_pwwn(port, plogi->port_name);
319 	if (rport) {
320 		/*
321 		 * Direct Attach P2P mode : handle address assigned by r-port.
322 		 */
323 		if ((!bfa_fcs_fabric_is_switched(port->fabric)) &&
324 			(memcmp((void *)&bfa_fcs_lport_get_pwwn(port),
325 			(void *)&plogi->port_name, sizeof(wwn_t)) < 0)) {
326 			port->pid  = rx_fchs->d_id;
327 			bfa_lps_set_n2n_pid(port->fabric->lps, rx_fchs->d_id);
328 			rport->pid = rx_fchs->s_id;
329 		}
330 		bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
331 		return;
332 	}
333 
334 	/*
335 	 * Next, lookup rport by PID.
336 	 */
337 	rport = bfa_fcs_lport_get_rport_by_pid(port, rx_fchs->s_id);
338 	if (!rport) {
339 		/*
340 		 * Inbound PLOGI from a new device.
341 		 */
342 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
343 		return;
344 	}
345 
346 	/*
347 	 * Rport is known only by PID.
348 	 */
349 	if (rport->pwwn) {
350 		/*
351 		 * This is a different device with the same pid. Old device
352 		 * disappeared. Send implicit LOGO to old device.
353 		 */
354 		WARN_ON(rport->pwwn == plogi->port_name);
355 		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
356 
357 		/*
358 		 * Inbound PLOGI from a new device (with old PID).
359 		 */
360 		bfa_fcs_rport_plogi_create(port, rx_fchs, plogi);
361 		return;
362 	}
363 
364 	/*
365 	 * PLOGI crossing each other.
366 	 */
367 	WARN_ON(rport->pwwn != WWN_NULL);
368 	bfa_fcs_rport_plogi(rport, rx_fchs, plogi);
369 }
370 
371 /*
372  * Process incoming ECHO.
373  * Since it does not require a login, it is processed here.
374  */
375 static void
bfa_fcs_lport_echo(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_echo_s * echo,u16 rx_len)376 bfa_fcs_lport_echo(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
377 		struct fc_echo_s *echo, u16 rx_len)
378 {
379 	struct fchs_s		fchs;
380 	struct bfa_fcxp_s	*fcxp;
381 	struct bfa_rport_s	*bfa_rport = NULL;
382 	int			len, pyld_len;
383 
384 	bfa_trc(port->fcs, rx_fchs->s_id);
385 	bfa_trc(port->fcs, rx_fchs->d_id);
386 
387 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
388 	if (!fcxp)
389 		return;
390 
391 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
392 				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
393 				rx_fchs->ox_id);
394 
395 	/*
396 	 * Copy the payload (if any) from the echo frame
397 	 */
398 	pyld_len = rx_len - sizeof(struct fchs_s);
399 	bfa_trc(port->fcs, rx_len);
400 	bfa_trc(port->fcs, pyld_len);
401 
402 	if (pyld_len > len)
403 		memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) +
404 			sizeof(struct fc_echo_s), (echo + 1),
405 			(pyld_len - sizeof(struct fc_echo_s)));
406 
407 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
408 			BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL,
409 			FC_MAX_PDUSZ, 0);
410 }
411 
412 /*
413  * Process incoming RNID.
414  * Since it does not require a login, it is processed here.
415  */
416 static void
bfa_fcs_lport_rnid(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs,struct fc_rnid_cmd_s * rnid,u16 rx_len)417 bfa_fcs_lport_rnid(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs,
418 		struct fc_rnid_cmd_s *rnid, u16 rx_len)
419 {
420 	struct fc_rnid_common_id_data_s common_id_data;
421 	struct fc_rnid_general_topology_data_s gen_topo_data;
422 	struct fchs_s	fchs;
423 	struct bfa_fcxp_s *fcxp;
424 	struct bfa_rport_s *bfa_rport = NULL;
425 	u16	len;
426 	u32	data_format;
427 
428 	bfa_trc(port->fcs, rx_fchs->s_id);
429 	bfa_trc(port->fcs, rx_fchs->d_id);
430 	bfa_trc(port->fcs, rx_len);
431 
432 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
433 	if (!fcxp)
434 		return;
435 
436 	/*
437 	 * Check Node Indentification Data Format
438 	 * We only support General Topology Discovery Format.
439 	 * For any other requested Data Formats, we return Common Node Id Data
440 	 * only, as per FC-LS.
441 	 */
442 	bfa_trc(port->fcs, rnid->node_id_data_format);
443 	if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) {
444 		data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY;
445 		/*
446 		 * Get General topology data for this port
447 		 */
448 		bfa_fs_port_get_gen_topo_data(port, &gen_topo_data);
449 	} else {
450 		data_format = RNID_NODEID_DATA_FORMAT_COMMON;
451 	}
452 
453 	/*
454 	 * Copy the Node Id Info
455 	 */
456 	common_id_data.port_name = bfa_fcs_lport_get_pwwn(port);
457 	common_id_data.node_name = bfa_fcs_lport_get_nwwn(port);
458 
459 	len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
460 				rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
461 				rx_fchs->ox_id, data_format, &common_id_data,
462 				&gen_topo_data);
463 
464 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
465 			BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
466 			FC_MAX_PDUSZ, 0);
467 }
468 
469 /*
470  *  Fill out General Topolpgy Discovery Data for RNID ELS.
471  */
472 static void
bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s * port,struct fc_rnid_general_topology_data_s * gen_topo_data)473 bfa_fs_port_get_gen_topo_data(struct bfa_fcs_lport_s *port,
474 			struct fc_rnid_general_topology_data_s *gen_topo_data)
475 {
476 	memset(gen_topo_data, 0,
477 		      sizeof(struct fc_rnid_general_topology_data_s));
478 
479 	gen_topo_data->asso_type = cpu_to_be32(RNID_ASSOCIATED_TYPE_HOST);
480 	gen_topo_data->phy_port_num = 0;	/* @todo */
481 	gen_topo_data->num_attached_nodes = cpu_to_be32(1);
482 }
483 
484 static void
bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s * port)485 bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
486 {
487 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
488 	char	lpwwn_buf[BFA_STRING_32];
489 
490 	bfa_trc(port->fcs, port->fabric->oper_type);
491 
492 	__port_action[port->fabric->fab_type].init(port);
493 	__port_action[port->fabric->fab_type].online(port);
494 
495 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
496 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
497 		"Logical port online: WWN = %s Role = %s\n",
498 		lpwwn_buf, "Initiator");
499 
500 	bfad->bfad_flags |= BFAD_PORT_ONLINE;
501 }
502 
503 static void
bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s * port)504 bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
505 {
506 	struct list_head	*qe, *qen;
507 	struct bfa_fcs_rport_s *rport;
508 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
509 	char    lpwwn_buf[BFA_STRING_32];
510 
511 	bfa_trc(port->fcs, port->fabric->oper_type);
512 
513 	__port_action[port->fabric->fab_type].offline(port);
514 
515 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
516 	if (bfa_sm_cmp_state(port->fabric,
517 			bfa_fcs_fabric_sm_online) == BFA_TRUE)
518 		BFA_LOG(KERN_ERR, bfad, bfa_log_level,
519 		"Logical port lost fabric connectivity: WWN = %s Role = %s\n",
520 		lpwwn_buf, "Initiator");
521 	else
522 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
523 		"Logical port taken offline: WWN = %s Role = %s\n",
524 		lpwwn_buf, "Initiator");
525 
526 	list_for_each_safe(qe, qen, &port->rport_q) {
527 		rport = (struct bfa_fcs_rport_s *) qe;
528 		bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
529 	}
530 }
531 
532 static void
bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s * port)533 bfa_fcs_lport_unknown_init(struct bfa_fcs_lport_s *port)
534 {
535 	WARN_ON(1);
536 }
537 
538 static void
bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s * port)539 bfa_fcs_lport_unknown_online(struct bfa_fcs_lport_s *port)
540 {
541 	WARN_ON(1);
542 }
543 
544 static void
bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s * port)545 bfa_fcs_lport_unknown_offline(struct bfa_fcs_lport_s *port)
546 {
547 	WARN_ON(1);
548 }
549 
550 static void
bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs)551 bfa_fcs_lport_abts_acc(struct bfa_fcs_lport_s *port, struct fchs_s *rx_fchs)
552 {
553 	struct fchs_s fchs;
554 	struct bfa_fcxp_s *fcxp;
555 	int		len;
556 
557 	bfa_trc(port->fcs, rx_fchs->d_id);
558 	bfa_trc(port->fcs, rx_fchs->s_id);
559 
560 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
561 	if (!fcxp)
562 		return;
563 
564 	len = fc_ba_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
565 			rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
566 			rx_fchs->ox_id, 0);
567 
568 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
569 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
570 			  FC_MAX_PDUSZ, 0);
571 }
572 static void
bfa_fcs_lport_deleted(struct bfa_fcs_lport_s * port)573 bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
574 {
575 	struct bfad_s *bfad = (struct bfad_s *)port->fcs->bfad;
576 	char    lpwwn_buf[BFA_STRING_32];
577 
578 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
579 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
580 		"Logical port deleted: WWN = %s Role = %s\n",
581 		lpwwn_buf, "Initiator");
582 
583 	/* Base port will be deleted by the OS driver */
584 	if (port->vport) {
585 		bfa_fcb_lport_delete(port->fcs->bfad, port->port_cfg.roles,
586 				port->fabric->vf_drv,
587 				port->vport ? port->vport->vport_drv : NULL);
588 		bfa_fcs_vport_delete_comp(port->vport);
589 	} else {
590 		bfa_wc_down(&port->fabric->wc);
591 	}
592 }
593 
594 
595 /*
596  * Unsolicited frame receive handling.
597  */
598 void
bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s * lport,struct fchs_s * fchs,u16 len)599 bfa_fcs_lport_uf_recv(struct bfa_fcs_lport_s *lport,
600 			struct fchs_s *fchs, u16 len)
601 {
602 	u32	pid = fchs->s_id;
603 	struct bfa_fcs_rport_s *rport = NULL;
604 	struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
605 
606 	bfa_stats(lport, uf_recvs);
607 	bfa_trc(lport->fcs, fchs->type);
608 
609 	if (!bfa_fcs_lport_is_online(lport)) {
610 		bfa_stats(lport, uf_recv_drops);
611 		return;
612 	}
613 
614 	/*
615 	 * First, handle ELSs that donot require a login.
616 	 */
617 	/*
618 	 * Handle PLOGI first
619 	 */
620 	if ((fchs->type == FC_TYPE_ELS) &&
621 		(els_cmd->els_code == FC_ELS_PLOGI)) {
622 		bfa_fcs_lport_plogi(lport, fchs, (struct fc_logi_s *) els_cmd);
623 		return;
624 	}
625 
626 	/*
627 	 * Handle ECHO separately.
628 	 */
629 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) {
630 		bfa_fcs_lport_echo(lport, fchs,
631 				(struct fc_echo_s *)els_cmd, len);
632 		return;
633 	}
634 
635 	/*
636 	 * Handle RNID separately.
637 	 */
638 	if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) {
639 		bfa_fcs_lport_rnid(lport, fchs,
640 			(struct fc_rnid_cmd_s *) els_cmd, len);
641 		return;
642 	}
643 
644 	if (fchs->type == FC_TYPE_BLS) {
645 		if ((fchs->routing == FC_RTG_BASIC_LINK) &&
646 				(fchs->cat_info == FC_CAT_ABTS))
647 			bfa_fcs_lport_abts_acc(lport, fchs);
648 		return;
649 	}
650 	/*
651 	 * look for a matching remote port ID
652 	 */
653 	rport = bfa_fcs_lport_get_rport_by_pid(lport, pid);
654 	if (rport) {
655 		bfa_trc(rport->fcs, fchs->s_id);
656 		bfa_trc(rport->fcs, fchs->d_id);
657 		bfa_trc(rport->fcs, fchs->type);
658 
659 		bfa_fcs_rport_uf_recv(rport, fchs, len);
660 		return;
661 	}
662 
663 	/*
664 	 * Only handles ELS frames for now.
665 	 */
666 	if (fchs->type != FC_TYPE_ELS) {
667 		bfa_trc(lport->fcs, fchs->s_id);
668 		bfa_trc(lport->fcs, fchs->d_id);
669 		/* ignore type FC_TYPE_FC_FSS */
670 		if (fchs->type != FC_TYPE_FC_FSS)
671 			bfa_sm_fault(lport->fcs, fchs->type);
672 		return;
673 	}
674 
675 	bfa_trc(lport->fcs, els_cmd->els_code);
676 	if (els_cmd->els_code == FC_ELS_RSCN) {
677 		bfa_fcs_lport_scn_process_rscn(lport, fchs, len);
678 		return;
679 	}
680 
681 	if (els_cmd->els_code == FC_ELS_LOGO) {
682 		/*
683 		 * @todo Handle LOGO frames received.
684 		 */
685 		return;
686 	}
687 
688 	if (els_cmd->els_code == FC_ELS_PRLI) {
689 		/*
690 		 * @todo Handle PRLI frames received.
691 		 */
692 		return;
693 	}
694 
695 	/*
696 	 * Unhandled ELS frames. Send a LS_RJT.
697 	 */
698 	bfa_fcs_lport_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP,
699 				 FC_LS_RJT_EXP_NO_ADDL_INFO);
700 
701 }
702 
703 /*
704  *   PID based Lookup for a R-Port in the Port R-Port Queue
705  */
706 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s * port,u32 pid)707 bfa_fcs_lport_get_rport_by_pid(struct bfa_fcs_lport_s *port, u32 pid)
708 {
709 	struct bfa_fcs_rport_s *rport;
710 	struct list_head	*qe;
711 
712 	list_for_each(qe, &port->rport_q) {
713 		rport = (struct bfa_fcs_rport_s *) qe;
714 		if (rport->pid == pid)
715 			return rport;
716 	}
717 
718 	bfa_trc(port->fcs, pid);
719 	return NULL;
720 }
721 
722 /*
723  *   PWWN based Lookup for a R-Port in the Port R-Port Queue
724  */
725 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s * port,wwn_t pwwn)726 bfa_fcs_lport_get_rport_by_pwwn(struct bfa_fcs_lport_s *port, wwn_t pwwn)
727 {
728 	struct bfa_fcs_rport_s *rport;
729 	struct list_head	*qe;
730 
731 	list_for_each(qe, &port->rport_q) {
732 		rport = (struct bfa_fcs_rport_s *) qe;
733 		if (wwn_is_equal(rport->pwwn, pwwn))
734 			return rport;
735 	}
736 
737 	bfa_trc(port->fcs, pwwn);
738 	return NULL;
739 }
740 
741 /*
742  *   NWWN based Lookup for a R-Port in the Port R-Port Queue
743  */
744 struct bfa_fcs_rport_s *
bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s * port,wwn_t nwwn)745 bfa_fcs_lport_get_rport_by_nwwn(struct bfa_fcs_lport_s *port, wwn_t nwwn)
746 {
747 	struct bfa_fcs_rport_s *rport;
748 	struct list_head	*qe;
749 
750 	list_for_each(qe, &port->rport_q) {
751 		rport = (struct bfa_fcs_rport_s *) qe;
752 		if (wwn_is_equal(rport->nwwn, nwwn))
753 			return rport;
754 	}
755 
756 	bfa_trc(port->fcs, nwwn);
757 	return NULL;
758 }
759 
760 /*
761  * Called by rport module when new rports are discovered.
762  */
763 void
bfa_fcs_lport_add_rport(struct bfa_fcs_lport_s * port,struct bfa_fcs_rport_s * rport)764 bfa_fcs_lport_add_rport(
765 	struct bfa_fcs_lport_s *port,
766 	struct bfa_fcs_rport_s *rport)
767 {
768 	list_add_tail(&rport->qe, &port->rport_q);
769 	port->num_rports++;
770 }
771 
772 /*
773  * Called by rport module to when rports are deleted.
774  */
775 void
bfa_fcs_lport_del_rport(struct bfa_fcs_lport_s * port,struct bfa_fcs_rport_s * rport)776 bfa_fcs_lport_del_rport(
777 	struct bfa_fcs_lport_s *port,
778 	struct bfa_fcs_rport_s *rport)
779 {
780 	WARN_ON(!bfa_q_is_on_q(&port->rport_q, rport));
781 	list_del(&rport->qe);
782 	port->num_rports--;
783 
784 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT);
785 }
786 
787 /*
788  * Called by fabric for base port when fabric login is complete.
789  * Called by vport for virtual ports when FDISC is complete.
790  */
791 void
bfa_fcs_lport_online(struct bfa_fcs_lport_s * port)792 bfa_fcs_lport_online(struct bfa_fcs_lport_s *port)
793 {
794 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE);
795 }
796 
797 /*
798  * Called by fabric for base port when fabric goes offline.
799  * Called by vport for virtual ports when virtual port becomes offline.
800  */
801 void
bfa_fcs_lport_offline(struct bfa_fcs_lport_s * port)802 bfa_fcs_lport_offline(struct bfa_fcs_lport_s *port)
803 {
804 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE);
805 }
806 
807 /*
808  * Called by fabric to delete base lport and associated resources.
809  *
810  * Called by vport to delete lport and associated resources. Should call
811  * bfa_fcs_vport_delete_comp() for vports on completion.
812  */
813 void
bfa_fcs_lport_delete(struct bfa_fcs_lport_s * port)814 bfa_fcs_lport_delete(struct bfa_fcs_lport_s *port)
815 {
816 	bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE);
817 }
818 
819 /*
820  * Return TRUE if port is online, else return FALSE
821  */
822 bfa_boolean_t
bfa_fcs_lport_is_online(struct bfa_fcs_lport_s * port)823 bfa_fcs_lport_is_online(struct bfa_fcs_lport_s *port)
824 {
825 	return bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online);
826 }
827 
828 /*
829   * Attach time initialization of logical ports.
830  */
831 void
bfa_fcs_lport_attach(struct bfa_fcs_lport_s * lport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_fcs_vport_s * vport)832 bfa_fcs_lport_attach(struct bfa_fcs_lport_s *lport, struct bfa_fcs_s *fcs,
833 		   u16 vf_id, struct bfa_fcs_vport_s *vport)
834 {
835 	lport->fcs = fcs;
836 	lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id);
837 	lport->vport = vport;
838 	lport->lp_tag = (vport) ? vport->lps->lp_tag :
839 				  lport->fabric->lps->lp_tag;
840 
841 	INIT_LIST_HEAD(&lport->rport_q);
842 	lport->num_rports = 0;
843 }
844 
845 /*
846  * Logical port initialization of base or virtual port.
847  * Called by fabric for base port or by vport for virtual ports.
848  */
849 
850 void
bfa_fcs_lport_init(struct bfa_fcs_lport_s * lport,struct bfa_lport_cfg_s * port_cfg)851 bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
852 	struct bfa_lport_cfg_s *port_cfg)
853 {
854 	struct bfa_fcs_vport_s *vport = lport->vport;
855 	struct bfad_s *bfad = (struct bfad_s *)lport->fcs->bfad;
856 	char    lpwwn_buf[BFA_STRING_32];
857 
858 	lport->port_cfg = *port_cfg;
859 
860 	lport->bfad_port = bfa_fcb_lport_new(lport->fcs->bfad, lport,
861 					lport->port_cfg.roles,
862 					lport->fabric->vf_drv,
863 					vport ? vport->vport_drv : NULL);
864 
865 	wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
866 	BFA_LOG(KERN_INFO, bfad, bfa_log_level,
867 		"New logical port created: WWN = %s Role = %s\n",
868 		lpwwn_buf, "Initiator");
869 
870 	bfa_sm_set_state(lport, bfa_fcs_lport_sm_uninit);
871 	bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE);
872 }
873 
874 /*
875  *  fcs_lport_api
876  */
877 
878 void
bfa_fcs_lport_get_attr(struct bfa_fcs_lport_s * port,struct bfa_lport_attr_s * port_attr)879 bfa_fcs_lport_get_attr(
880 	struct bfa_fcs_lport_s *port,
881 	struct bfa_lport_attr_s *port_attr)
882 {
883 	if (bfa_sm_cmp_state(port, bfa_fcs_lport_sm_online))
884 		port_attr->pid = port->pid;
885 	else
886 		port_attr->pid = 0;
887 
888 	port_attr->port_cfg = port->port_cfg;
889 
890 	if (port->fabric) {
891 		port_attr->port_type = port->fabric->oper_type;
892 		port_attr->loopback = bfa_sm_cmp_state(port->fabric,
893 				bfa_fcs_fabric_sm_loopback);
894 		port_attr->authfail =
895 			bfa_sm_cmp_state(port->fabric,
896 				bfa_fcs_fabric_sm_auth_failed);
897 		port_attr->fabric_name  = bfa_fcs_lport_get_fabric_name(port);
898 		memcpy(port_attr->fabric_ip_addr,
899 			bfa_fcs_lport_get_fabric_ipaddr(port),
900 			BFA_FCS_FABRIC_IPADDR_SZ);
901 
902 		if (port->vport != NULL) {
903 			port_attr->port_type = BFA_PORT_TYPE_VPORT;
904 			port_attr->fpma_mac =
905 				port->vport->lps->lp_mac;
906 		} else {
907 			port_attr->fpma_mac =
908 				port->fabric->lps->lp_mac;
909 		}
910 	} else {
911 		port_attr->port_type = BFA_PORT_TYPE_UNKNOWN;
912 		port_attr->state = BFA_LPORT_UNINIT;
913 	}
914 }
915 
916 /*
917  *  bfa_fcs_lport_fab port fab functions
918  */
919 
920 /*
921  *   Called by port to initialize fabric services of the base port.
922  */
923 static void
bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s * port)924 bfa_fcs_lport_fab_init(struct bfa_fcs_lport_s *port)
925 {
926 	bfa_fcs_lport_ns_init(port);
927 	bfa_fcs_lport_scn_init(port);
928 	bfa_fcs_lport_ms_init(port);
929 }
930 
931 /*
932  *   Called by port to notify transition to online state.
933  */
934 static void
bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s * port)935 bfa_fcs_lport_fab_online(struct bfa_fcs_lport_s *port)
936 {
937 	bfa_fcs_lport_ns_online(port);
938 	bfa_fcs_lport_scn_online(port);
939 }
940 
941 /*
942  *   Called by port to notify transition to offline state.
943  */
944 static void
bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s * port)945 bfa_fcs_lport_fab_offline(struct bfa_fcs_lport_s *port)
946 {
947 	bfa_fcs_lport_ns_offline(port);
948 	bfa_fcs_lport_scn_offline(port);
949 	bfa_fcs_lport_ms_offline(port);
950 }
951 
952 /*
953  *  bfa_fcs_lport_n2n  functions
954  */
955 
956 /*
957  *   Called by fcs/port to initialize N2N topology.
958  */
959 static void
bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s * port)960 bfa_fcs_lport_n2n_init(struct bfa_fcs_lport_s *port)
961 {
962 }
963 
964 /*
965  *   Called by fcs/port to notify transition to online state.
966  */
967 static void
bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s * port)968 bfa_fcs_lport_n2n_online(struct bfa_fcs_lport_s *port)
969 {
970 	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
971 	struct bfa_lport_cfg_s *pcfg = &port->port_cfg;
972 	struct bfa_fcs_rport_s *rport;
973 
974 	bfa_trc(port->fcs, pcfg->pwwn);
975 
976 	/*
977 	 * If our PWWN is > than that of the r-port, we have to initiate PLOGI
978 	 * and assign an Address. if not, we need to wait for its PLOGI.
979 	 *
980 	 * If our PWWN is < than that of the remote port, it will send a PLOGI
981 	 * with the PIDs assigned. The rport state machine take care of this
982 	 * incoming PLOGI.
983 	 */
984 	if (memcmp
985 	    ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn,
986 	     sizeof(wwn_t)) > 0) {
987 		port->pid = N2N_LOCAL_PID;
988 		bfa_lps_set_n2n_pid(port->fabric->lps, N2N_LOCAL_PID);
989 		/*
990 		 * First, check if we know the device by pwwn.
991 		 */
992 		rport = bfa_fcs_lport_get_rport_by_pwwn(port,
993 							n2n_port->rem_port_wwn);
994 		if (rport) {
995 			bfa_trc(port->fcs, rport->pid);
996 			bfa_trc(port->fcs, rport->pwwn);
997 			rport->pid = N2N_REMOTE_PID;
998 			bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
999 			return;
1000 		}
1001 
1002 		/*
1003 		 * In n2n there can be only one rport. Delete the old one
1004 		 * whose pid should be zero, because it is offline.
1005 		 */
1006 		if (port->num_rports > 0) {
1007 			rport = bfa_fcs_lport_get_rport_by_pid(port, 0);
1008 			WARN_ON(rport == NULL);
1009 			if (rport) {
1010 				bfa_trc(port->fcs, rport->pwwn);
1011 				bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
1012 			}
1013 		}
1014 		bfa_fcs_rport_create(port, N2N_REMOTE_PID);
1015 	}
1016 }
1017 
1018 /*
1019  *   Called by fcs/port to notify transition to offline state.
1020  */
1021 static void
bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s * port)1022 bfa_fcs_lport_n2n_offline(struct bfa_fcs_lport_s *port)
1023 {
1024 	struct bfa_fcs_lport_n2n_s *n2n_port = &port->port_topo.pn2n;
1025 
1026 	bfa_trc(port->fcs, port->pid);
1027 	port->pid = 0;
1028 	n2n_port->rem_port_wwn = 0;
1029 	n2n_port->reply_oxid = 0;
1030 }
1031 
1032 #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2
1033 
1034 /*
1035  * forward declarations
1036  */
1037 static void     bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg,
1038 					    struct bfa_fcxp_s *fcxp_alloced);
1039 static void     bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg,
1040 					    struct bfa_fcxp_s *fcxp_alloced);
1041 static void     bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg,
1042 					   struct bfa_fcxp_s *fcxp_alloced);
1043 static void     bfa_fcs_lport_fdmi_rhba_response(void *fcsarg,
1044 						struct bfa_fcxp_s *fcxp,
1045 						void *cbarg,
1046 						bfa_status_t req_status,
1047 						u32 rsp_len,
1048 						u32 resid_len,
1049 						struct fchs_s *rsp_fchs);
1050 static void     bfa_fcs_lport_fdmi_rprt_response(void *fcsarg,
1051 						struct bfa_fcxp_s *fcxp,
1052 						void *cbarg,
1053 						bfa_status_t req_status,
1054 						u32 rsp_len,
1055 						u32 resid_len,
1056 						struct fchs_s *rsp_fchs);
1057 static void     bfa_fcs_lport_fdmi_rpa_response(void *fcsarg,
1058 					       struct bfa_fcxp_s *fcxp,
1059 					       void *cbarg,
1060 					       bfa_status_t req_status,
1061 					       u32 rsp_len,
1062 					       u32 resid_len,
1063 					       struct fchs_s *rsp_fchs);
1064 static void     bfa_fcs_lport_fdmi_timeout(void *arg);
1065 static u16 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1066 						  u8 *pyld);
1067 static u16 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1068 						  u8 *pyld);
1069 static u16 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi,
1070 						 u8 *pyld);
1071 static u16 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *
1072 						       fdmi, u8 *pyld);
1073 static void	bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1074 				 struct bfa_fcs_fdmi_hba_attr_s *hba_attr);
1075 static void	bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
1076 				  struct bfa_fcs_fdmi_port_attr_s *port_attr);
1077 /*
1078  *  fcs_fdmi_sm FCS FDMI state machine
1079  */
1080 
1081 /*
1082  *  FDMI State Machine events
1083  */
1084 enum port_fdmi_event {
1085 	FDMISM_EVENT_PORT_ONLINE = 1,
1086 	FDMISM_EVENT_PORT_OFFLINE = 2,
1087 	FDMISM_EVENT_RSP_OK = 4,
1088 	FDMISM_EVENT_RSP_ERROR = 5,
1089 	FDMISM_EVENT_TIMEOUT = 6,
1090 	FDMISM_EVENT_RHBA_SENT = 7,
1091 	FDMISM_EVENT_RPRT_SENT = 8,
1092 	FDMISM_EVENT_RPA_SENT = 9,
1093 };
1094 
1095 static void     bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1096 					     enum port_fdmi_event event);
1097 static void     bfa_fcs_lport_fdmi_sm_sending_rhba(
1098 				struct bfa_fcs_lport_fdmi_s *fdmi,
1099 				enum port_fdmi_event event);
1100 static void     bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1101 					  enum port_fdmi_event event);
1102 static void     bfa_fcs_lport_fdmi_sm_rhba_retry(
1103 				struct bfa_fcs_lport_fdmi_s *fdmi,
1104 				enum port_fdmi_event event);
1105 static void     bfa_fcs_lport_fdmi_sm_sending_rprt(
1106 				struct bfa_fcs_lport_fdmi_s *fdmi,
1107 				enum port_fdmi_event event);
1108 static void     bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1109 					  enum port_fdmi_event event);
1110 static void     bfa_fcs_lport_fdmi_sm_rprt_retry(
1111 				struct bfa_fcs_lport_fdmi_s *fdmi,
1112 				enum port_fdmi_event event);
1113 static void     bfa_fcs_lport_fdmi_sm_sending_rpa(
1114 				struct bfa_fcs_lport_fdmi_s *fdmi,
1115 				enum port_fdmi_event event);
1116 static void     bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1117 					 enum port_fdmi_event event);
1118 static void     bfa_fcs_lport_fdmi_sm_rpa_retry(
1119 				struct bfa_fcs_lport_fdmi_s *fdmi,
1120 				enum port_fdmi_event event);
1121 static void     bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1122 					    enum port_fdmi_event event);
1123 static void     bfa_fcs_lport_fdmi_sm_disabled(
1124 				struct bfa_fcs_lport_fdmi_s *fdmi,
1125 				enum port_fdmi_event event);
1126 /*
1127  *	Start in offline state - awaiting MS to send start.
1128  */
1129 static void
bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1130 bfa_fcs_lport_fdmi_sm_offline(struct bfa_fcs_lport_fdmi_s *fdmi,
1131 			     enum port_fdmi_event event)
1132 {
1133 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1134 
1135 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1136 	bfa_trc(port->fcs, event);
1137 
1138 	fdmi->retry_cnt = 0;
1139 
1140 	switch (event) {
1141 	case FDMISM_EVENT_PORT_ONLINE:
1142 		if (port->vport) {
1143 			/*
1144 			 * For Vports, register a new port.
1145 			 */
1146 			bfa_sm_set_state(fdmi,
1147 					 bfa_fcs_lport_fdmi_sm_sending_rprt);
1148 			bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1149 		} else {
1150 			/*
1151 			 * For a base port, we should first register the HBA
1152 			 * attribute. The HBA attribute also contains the base
1153 			 *  port registration.
1154 			 */
1155 			bfa_sm_set_state(fdmi,
1156 					 bfa_fcs_lport_fdmi_sm_sending_rhba);
1157 			bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1158 		}
1159 		break;
1160 
1161 	case FDMISM_EVENT_PORT_OFFLINE:
1162 		break;
1163 
1164 	default:
1165 		bfa_sm_fault(port->fcs, event);
1166 	}
1167 }
1168 
1169 static void
bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1170 bfa_fcs_lport_fdmi_sm_sending_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1171 				  enum port_fdmi_event event)
1172 {
1173 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1174 
1175 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1176 	bfa_trc(port->fcs, event);
1177 
1178 	switch (event) {
1179 	case FDMISM_EVENT_RHBA_SENT:
1180 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rhba);
1181 		break;
1182 
1183 	case FDMISM_EVENT_PORT_OFFLINE:
1184 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1185 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1186 					   &fdmi->fcxp_wqe);
1187 		break;
1188 
1189 	default:
1190 		bfa_sm_fault(port->fcs, event);
1191 	}
1192 }
1193 
1194 static void
bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1195 bfa_fcs_lport_fdmi_sm_rhba(struct bfa_fcs_lport_fdmi_s *fdmi,
1196 			enum port_fdmi_event event)
1197 {
1198 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1199 
1200 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1201 	bfa_trc(port->fcs, event);
1202 
1203 	switch (event) {
1204 	case FDMISM_EVENT_RSP_ERROR:
1205 		/*
1206 		 * if max retries have not been reached, start timer for a
1207 		 * delayed retry
1208 		 */
1209 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1210 			bfa_sm_set_state(fdmi,
1211 					bfa_fcs_lport_fdmi_sm_rhba_retry);
1212 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1213 					    &fdmi->timer,
1214 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1215 					    BFA_FCS_RETRY_TIMEOUT);
1216 		} else {
1217 			/*
1218 			 * set state to offline
1219 			 */
1220 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1221 		}
1222 		break;
1223 
1224 	case FDMISM_EVENT_RSP_OK:
1225 		/*
1226 		 * Initiate Register Port Attributes
1227 		 */
1228 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1229 		fdmi->retry_cnt = 0;
1230 		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1231 		break;
1232 
1233 	case FDMISM_EVENT_PORT_OFFLINE:
1234 		bfa_fcxp_discard(fdmi->fcxp);
1235 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1236 		break;
1237 
1238 	default:
1239 		bfa_sm_fault(port->fcs, event);
1240 	}
1241 }
1242 
1243 static void
bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1244 bfa_fcs_lport_fdmi_sm_rhba_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1245 				enum port_fdmi_event event)
1246 {
1247 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1248 
1249 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1250 	bfa_trc(port->fcs, event);
1251 
1252 	switch (event) {
1253 	case FDMISM_EVENT_TIMEOUT:
1254 		/*
1255 		 * Retry Timer Expired. Re-send
1256 		 */
1257 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rhba);
1258 		bfa_fcs_lport_fdmi_send_rhba(fdmi, NULL);
1259 		break;
1260 
1261 	case FDMISM_EVENT_PORT_OFFLINE:
1262 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1263 		bfa_timer_stop(&fdmi->timer);
1264 		break;
1265 
1266 	default:
1267 		bfa_sm_fault(port->fcs, event);
1268 	}
1269 }
1270 
1271 /*
1272 * RPRT : Register Port
1273  */
1274 static void
bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1275 bfa_fcs_lport_fdmi_sm_sending_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1276 				  enum port_fdmi_event event)
1277 {
1278 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1279 
1280 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1281 	bfa_trc(port->fcs, event);
1282 
1283 	switch (event) {
1284 	case FDMISM_EVENT_RPRT_SENT:
1285 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rprt);
1286 		break;
1287 
1288 	case FDMISM_EVENT_PORT_OFFLINE:
1289 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1290 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1291 					   &fdmi->fcxp_wqe);
1292 		break;
1293 
1294 	default:
1295 		bfa_sm_fault(port->fcs, event);
1296 	}
1297 }
1298 
1299 static void
bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1300 bfa_fcs_lport_fdmi_sm_rprt(struct bfa_fcs_lport_fdmi_s *fdmi,
1301 			enum port_fdmi_event event)
1302 {
1303 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1304 
1305 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1306 	bfa_trc(port->fcs, event);
1307 
1308 	switch (event) {
1309 	case FDMISM_EVENT_RSP_ERROR:
1310 		/*
1311 		 * if max retries have not been reached, start timer for a
1312 		 * delayed retry
1313 		 */
1314 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1315 			bfa_sm_set_state(fdmi,
1316 					bfa_fcs_lport_fdmi_sm_rprt_retry);
1317 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1318 					    &fdmi->timer,
1319 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1320 					    BFA_FCS_RETRY_TIMEOUT);
1321 
1322 		} else {
1323 			/*
1324 			 * set state to offline
1325 			 */
1326 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1327 			fdmi->retry_cnt = 0;
1328 		}
1329 		break;
1330 
1331 	case FDMISM_EVENT_RSP_OK:
1332 		fdmi->retry_cnt = 0;
1333 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1334 		break;
1335 
1336 	case FDMISM_EVENT_PORT_OFFLINE:
1337 		bfa_fcxp_discard(fdmi->fcxp);
1338 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1339 		break;
1340 
1341 	default:
1342 		bfa_sm_fault(port->fcs, event);
1343 	}
1344 }
1345 
1346 static void
bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1347 bfa_fcs_lport_fdmi_sm_rprt_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1348 				enum port_fdmi_event event)
1349 {
1350 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1351 
1352 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1353 	bfa_trc(port->fcs, event);
1354 
1355 	switch (event) {
1356 	case FDMISM_EVENT_TIMEOUT:
1357 		/*
1358 		 * Retry Timer Expired. Re-send
1359 		 */
1360 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rprt);
1361 		bfa_fcs_lport_fdmi_send_rprt(fdmi, NULL);
1362 		break;
1363 
1364 	case FDMISM_EVENT_PORT_OFFLINE:
1365 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1366 		bfa_timer_stop(&fdmi->timer);
1367 		break;
1368 
1369 	default:
1370 		bfa_sm_fault(port->fcs, event);
1371 	}
1372 }
1373 
1374 /*
1375  * Register Port Attributes
1376  */
1377 static void
bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1378 bfa_fcs_lport_fdmi_sm_sending_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1379 				 enum port_fdmi_event event)
1380 {
1381 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1382 
1383 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1384 	bfa_trc(port->fcs, event);
1385 
1386 	switch (event) {
1387 	case FDMISM_EVENT_RPA_SENT:
1388 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa);
1389 		break;
1390 
1391 	case FDMISM_EVENT_PORT_OFFLINE:
1392 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1393 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port),
1394 					   &fdmi->fcxp_wqe);
1395 		break;
1396 
1397 	default:
1398 		bfa_sm_fault(port->fcs, event);
1399 	}
1400 }
1401 
1402 static void
bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1403 bfa_fcs_lport_fdmi_sm_rpa(struct bfa_fcs_lport_fdmi_s *fdmi,
1404 			enum port_fdmi_event event)
1405 {
1406 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1407 
1408 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1409 	bfa_trc(port->fcs, event);
1410 
1411 	switch (event) {
1412 	case FDMISM_EVENT_RSP_ERROR:
1413 		/*
1414 		 * if max retries have not been reached, start timer for a
1415 		 * delayed retry
1416 		 */
1417 		if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) {
1418 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_rpa_retry);
1419 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port),
1420 					    &fdmi->timer,
1421 					    bfa_fcs_lport_fdmi_timeout, fdmi,
1422 					    BFA_FCS_RETRY_TIMEOUT);
1423 		} else {
1424 			/*
1425 			 * set state to offline
1426 			 */
1427 			bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1428 			fdmi->retry_cnt = 0;
1429 		}
1430 		break;
1431 
1432 	case FDMISM_EVENT_RSP_OK:
1433 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_online);
1434 		fdmi->retry_cnt = 0;
1435 		break;
1436 
1437 	case FDMISM_EVENT_PORT_OFFLINE:
1438 		bfa_fcxp_discard(fdmi->fcxp);
1439 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1440 		break;
1441 
1442 	default:
1443 		bfa_sm_fault(port->fcs, event);
1444 	}
1445 }
1446 
1447 static void
bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1448 bfa_fcs_lport_fdmi_sm_rpa_retry(struct bfa_fcs_lport_fdmi_s *fdmi,
1449 			       enum port_fdmi_event event)
1450 {
1451 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1452 
1453 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1454 	bfa_trc(port->fcs, event);
1455 
1456 	switch (event) {
1457 	case FDMISM_EVENT_TIMEOUT:
1458 		/*
1459 		 * Retry Timer Expired. Re-send
1460 		 */
1461 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_sending_rpa);
1462 		bfa_fcs_lport_fdmi_send_rpa(fdmi, NULL);
1463 		break;
1464 
1465 	case FDMISM_EVENT_PORT_OFFLINE:
1466 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1467 		bfa_timer_stop(&fdmi->timer);
1468 		break;
1469 
1470 	default:
1471 		bfa_sm_fault(port->fcs, event);
1472 	}
1473 }
1474 
1475 static void
bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1476 bfa_fcs_lport_fdmi_sm_online(struct bfa_fcs_lport_fdmi_s *fdmi,
1477 				enum port_fdmi_event event)
1478 {
1479 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1480 
1481 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1482 	bfa_trc(port->fcs, event);
1483 
1484 	switch (event) {
1485 	case FDMISM_EVENT_PORT_OFFLINE:
1486 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
1487 		break;
1488 
1489 	default:
1490 		bfa_sm_fault(port->fcs, event);
1491 	}
1492 }
1493 /*
1494  *  FDMI is disabled state.
1495  */
1496 static void
bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s * fdmi,enum port_fdmi_event event)1497 bfa_fcs_lport_fdmi_sm_disabled(struct bfa_fcs_lport_fdmi_s *fdmi,
1498 			     enum port_fdmi_event event)
1499 {
1500 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1501 
1502 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1503 	bfa_trc(port->fcs, event);
1504 
1505 	/* No op State. It can only be enabled at Driver Init. */
1506 }
1507 
1508 /*
1509 *  RHBA : Register HBA Attributes.
1510  */
1511 static void
bfa_fcs_lport_fdmi_send_rhba(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)1512 bfa_fcs_lport_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1513 {
1514 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1515 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1516 	struct fchs_s fchs;
1517 	int             len, attr_len;
1518 	struct bfa_fcxp_s *fcxp;
1519 	u8        *pyld;
1520 
1521 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1522 
1523 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1524 	if (!fcxp) {
1525 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1526 					bfa_fcs_lport_fdmi_send_rhba, fdmi);
1527 		return;
1528 	}
1529 	fdmi->fcxp = fcxp;
1530 
1531 	pyld = bfa_fcxp_get_reqbuf(fcxp);
1532 	memset(pyld, 0, FC_MAX_PDUSZ);
1533 
1534 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1535 				   FDMI_RHBA);
1536 
1537 	attr_len =
1538 		bfa_fcs_lport_fdmi_build_rhba_pyld(fdmi,
1539 					  (u8 *) ((struct ct_hdr_s *) pyld
1540 						       + 1));
1541 
1542 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1543 			  FC_CLASS_3, (len + attr_len), &fchs,
1544 			  bfa_fcs_lport_fdmi_rhba_response, (void *)fdmi,
1545 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1546 
1547 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT);
1548 }
1549 
1550 static          u16
bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)1551 bfa_fcs_lport_fdmi_build_rhba_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1552 {
1553 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1554 	struct bfa_fcs_fdmi_hba_attr_s hba_attr;
1555 	struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr;
1556 	struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld;
1557 	struct fdmi_attr_s *attr;
1558 	u8        *curr_ptr;
1559 	u16        len, count;
1560 	u16	templen;
1561 
1562 	/*
1563 	 * get hba attributes
1564 	 */
1565 	bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr);
1566 
1567 	rhba->hba_id = bfa_fcs_lport_get_pwwn(port);
1568 	rhba->port_list.num_ports = cpu_to_be32(1);
1569 	rhba->port_list.port_entry = bfa_fcs_lport_get_pwwn(port);
1570 
1571 	len = sizeof(rhba->hba_id) + sizeof(rhba->port_list);
1572 
1573 	count = 0;
1574 	len += sizeof(rhba->hba_attr_blk.attr_count);
1575 
1576 	/*
1577 	 * fill out the invididual entries of the HBA attrib Block
1578 	 */
1579 	curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr;
1580 
1581 	/*
1582 	 * Node Name
1583 	 */
1584 	attr = (struct fdmi_attr_s *) curr_ptr;
1585 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_NODENAME);
1586 	templen = sizeof(wwn_t);
1587 	memcpy(attr->value, &bfa_fcs_lport_get_nwwn(port), templen);
1588 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1589 	len += templen;
1590 	count++;
1591 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1592 			     sizeof(templen));
1593 
1594 	/*
1595 	 * Manufacturer
1596 	 */
1597 	attr = (struct fdmi_attr_s *) curr_ptr;
1598 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MANUFACTURER);
1599 	templen = (u16) strlen(fcs_hba_attr->manufacturer);
1600 	memcpy(attr->value, fcs_hba_attr->manufacturer, templen);
1601 	templen = fc_roundup(templen, sizeof(u32));
1602 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1603 	len += templen;
1604 	count++;
1605 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1606 			     sizeof(templen));
1607 
1608 	/*
1609 	 * Serial Number
1610 	 */
1611 	attr = (struct fdmi_attr_s *) curr_ptr;
1612 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_SERIALNUM);
1613 	templen = (u16) strlen(fcs_hba_attr->serial_num);
1614 	memcpy(attr->value, fcs_hba_attr->serial_num, templen);
1615 	templen = fc_roundup(templen, sizeof(u32));
1616 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1617 	len += templen;
1618 	count++;
1619 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1620 			     sizeof(templen));
1621 
1622 	/*
1623 	 * Model
1624 	 */
1625 	attr = (struct fdmi_attr_s *) curr_ptr;
1626 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL);
1627 	templen = (u16) strlen(fcs_hba_attr->model);
1628 	memcpy(attr->value, fcs_hba_attr->model, templen);
1629 	templen = fc_roundup(templen, sizeof(u32));
1630 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1631 	len += templen;
1632 	count++;
1633 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1634 			     sizeof(templen));
1635 
1636 	/*
1637 	 * Model Desc
1638 	 */
1639 	attr = (struct fdmi_attr_s *) curr_ptr;
1640 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MODEL_DESC);
1641 	templen = (u16) strlen(fcs_hba_attr->model_desc);
1642 	memcpy(attr->value, fcs_hba_attr->model_desc, templen);
1643 	templen = fc_roundup(templen, sizeof(u32));
1644 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1645 	len += templen;
1646 	count++;
1647 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1648 			     sizeof(templen));
1649 
1650 	/*
1651 	 * H/W Version
1652 	 */
1653 	if (fcs_hba_attr->hw_version[0] != '\0') {
1654 		attr = (struct fdmi_attr_s *) curr_ptr;
1655 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_HW_VERSION);
1656 		templen = (u16) strlen(fcs_hba_attr->hw_version);
1657 		memcpy(attr->value, fcs_hba_attr->hw_version, templen);
1658 		templen = fc_roundup(templen, sizeof(u32));
1659 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1660 		len += templen;
1661 		count++;
1662 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1663 					 sizeof(templen));
1664 	}
1665 
1666 	/*
1667 	 * Driver Version
1668 	 */
1669 	attr = (struct fdmi_attr_s *) curr_ptr;
1670 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_DRIVER_VERSION);
1671 	templen = (u16) strlen(fcs_hba_attr->driver_version);
1672 	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1673 	templen = fc_roundup(templen, sizeof(u32));
1674 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1675 	len += templen;;
1676 	count++;
1677 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1678 			     sizeof(templen));
1679 
1680 	/*
1681 	 * Option Rom Version
1682 	 */
1683 	if (fcs_hba_attr->option_rom_ver[0] != '\0') {
1684 		attr = (struct fdmi_attr_s *) curr_ptr;
1685 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_ROM_VERSION);
1686 		templen = (u16) strlen(fcs_hba_attr->option_rom_ver);
1687 		memcpy(attr->value, fcs_hba_attr->option_rom_ver, templen);
1688 		templen = fc_roundup(templen, sizeof(u32));
1689 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1690 		len += templen;
1691 		count++;
1692 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1693 					 sizeof(templen));
1694 	}
1695 
1696 	/*
1697 	 * f/w Version = driver version
1698 	 */
1699 	attr = (struct fdmi_attr_s *) curr_ptr;
1700 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_FW_VERSION);
1701 	templen = (u16) strlen(fcs_hba_attr->driver_version);
1702 	memcpy(attr->value, fcs_hba_attr->driver_version, templen);
1703 	templen = fc_roundup(templen, sizeof(u32));
1704 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1705 	len += templen;
1706 	count++;
1707 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1708 			     sizeof(templen));
1709 
1710 	/*
1711 	 * OS Name
1712 	 */
1713 	if (fcs_hba_attr->os_name[0] != '\0') {
1714 		attr = (struct fdmi_attr_s *) curr_ptr;
1715 		attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_OS_NAME);
1716 		templen = (u16) strlen(fcs_hba_attr->os_name);
1717 		memcpy(attr->value, fcs_hba_attr->os_name, templen);
1718 		templen = fc_roundup(templen, sizeof(u32));
1719 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1720 		len += templen;
1721 		count++;
1722 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1723 					sizeof(templen));
1724 	}
1725 
1726 	/*
1727 	 * MAX_CT_PAYLOAD
1728 	 */
1729 	attr = (struct fdmi_attr_s *) curr_ptr;
1730 	attr->type = cpu_to_be16(FDMI_HBA_ATTRIB_MAX_CT);
1731 	templen = sizeof(fcs_hba_attr->max_ct_pyld);
1732 	memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, templen);
1733 	len += templen;
1734 	count++;
1735 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1736 			     sizeof(templen));
1737 
1738 	/*
1739 	 * Update size of payload
1740 	 */
1741 	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1742 
1743 	rhba->hba_attr_blk.attr_count = cpu_to_be32(count);
1744 	return len;
1745 }
1746 
1747 static void
bfa_fcs_lport_fdmi_rhba_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)1748 bfa_fcs_lport_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1749 				void *cbarg, bfa_status_t req_status,
1750 				u32 rsp_len, u32 resid_len,
1751 				struct fchs_s *rsp_fchs)
1752 {
1753 	struct bfa_fcs_lport_fdmi_s *fdmi =
1754 				(struct bfa_fcs_lport_fdmi_s *) cbarg;
1755 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1756 	struct ct_hdr_s *cthdr = NULL;
1757 
1758 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1759 
1760 	/*
1761 	 * Sanity Checks
1762 	 */
1763 	if (req_status != BFA_STATUS_OK) {
1764 		bfa_trc(port->fcs, req_status);
1765 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1766 		return;
1767 	}
1768 
1769 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1770 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1771 
1772 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1773 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1774 		return;
1775 	}
1776 
1777 	bfa_trc(port->fcs, cthdr->reason_code);
1778 	bfa_trc(port->fcs, cthdr->exp_code);
1779 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1780 }
1781 
1782 /*
1783 *  RPRT : Register Port
1784  */
1785 static void
bfa_fcs_lport_fdmi_send_rprt(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)1786 bfa_fcs_lport_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
1787 {
1788 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
1789 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1790 	struct fchs_s fchs;
1791 	u16        len, attr_len;
1792 	struct bfa_fcxp_s *fcxp;
1793 	u8        *pyld;
1794 
1795 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1796 
1797 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
1798 	if (!fcxp) {
1799 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
1800 					bfa_fcs_lport_fdmi_send_rprt, fdmi);
1801 		return;
1802 	}
1803 	fdmi->fcxp = fcxp;
1804 
1805 	pyld = bfa_fcxp_get_reqbuf(fcxp);
1806 	memset(pyld, 0, FC_MAX_PDUSZ);
1807 
1808 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
1809 				   FDMI_RPRT);
1810 
1811 	attr_len =
1812 		bfa_fcs_lport_fdmi_build_rprt_pyld(fdmi,
1813 					  (u8 *) ((struct ct_hdr_s *) pyld
1814 						       + 1));
1815 
1816 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
1817 			  FC_CLASS_3, len + attr_len, &fchs,
1818 			  bfa_fcs_lport_fdmi_rprt_response, (void *)fdmi,
1819 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
1820 
1821 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT);
1822 }
1823 
1824 /*
1825  * This routine builds Port Attribute Block that used in RPA, RPRT commands.
1826  */
1827 static          u16
bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)1828 bfa_fcs_lport_fdmi_build_portattr_block(struct bfa_fcs_lport_fdmi_s *fdmi,
1829 				       u8 *pyld)
1830 {
1831 	struct bfa_fcs_fdmi_port_attr_s fcs_port_attr;
1832 	struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld;
1833 	struct fdmi_attr_s *attr;
1834 	u8        *curr_ptr;
1835 	u16        len;
1836 	u8	count = 0;
1837 	u16	templen;
1838 
1839 	/*
1840 	 * get port attributes
1841 	 */
1842 	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
1843 
1844 	len = sizeof(port_attrib->attr_count);
1845 
1846 	/*
1847 	 * fill out the invididual entries
1848 	 */
1849 	curr_ptr = (u8 *) &port_attrib->port_attr;
1850 
1851 	/*
1852 	 * FC4 Types
1853 	 */
1854 	attr = (struct fdmi_attr_s *) curr_ptr;
1855 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FC4_TYPES);
1856 	templen = sizeof(fcs_port_attr.supp_fc4_types);
1857 	memcpy(attr->value, fcs_port_attr.supp_fc4_types, templen);
1858 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1859 	len += templen;
1860 	++count;
1861 	attr->len =
1862 		cpu_to_be16(templen + sizeof(attr->type) +
1863 			     sizeof(templen));
1864 
1865 	/*
1866 	 * Supported Speed
1867 	 */
1868 	attr = (struct fdmi_attr_s *) curr_ptr;
1869 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_SUPP_SPEED);
1870 	templen = sizeof(fcs_port_attr.supp_speed);
1871 	memcpy(attr->value, &fcs_port_attr.supp_speed, templen);
1872 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1873 	len += templen;
1874 	++count;
1875 	attr->len =
1876 		cpu_to_be16(templen + sizeof(attr->type) +
1877 			     sizeof(templen));
1878 
1879 	/*
1880 	 * current Port Speed
1881 	 */
1882 	attr = (struct fdmi_attr_s *) curr_ptr;
1883 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_PORT_SPEED);
1884 	templen = sizeof(fcs_port_attr.curr_speed);
1885 	memcpy(attr->value, &fcs_port_attr.curr_speed, templen);
1886 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1887 	len += templen;
1888 	++count;
1889 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1890 			     sizeof(templen));
1891 
1892 	/*
1893 	 * max frame size
1894 	 */
1895 	attr = (struct fdmi_attr_s *) curr_ptr;
1896 	attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_FRAME_SIZE);
1897 	templen = sizeof(fcs_port_attr.max_frm_size);
1898 	memcpy(attr->value, &fcs_port_attr.max_frm_size, templen);
1899 	curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1900 	len += templen;
1901 	++count;
1902 	attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1903 			     sizeof(templen));
1904 
1905 	/*
1906 	 * OS Device Name
1907 	 */
1908 	if (fcs_port_attr.os_device_name[0] != '\0') {
1909 		attr = (struct fdmi_attr_s *) curr_ptr;
1910 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_DEV_NAME);
1911 		templen = (u16) strlen(fcs_port_attr.os_device_name);
1912 		memcpy(attr->value, fcs_port_attr.os_device_name, templen);
1913 		templen = fc_roundup(templen, sizeof(u32));
1914 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1915 		len += templen;
1916 		++count;
1917 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1918 					sizeof(templen));
1919 	}
1920 	/*
1921 	 * Host Name
1922 	 */
1923 	if (fcs_port_attr.host_name[0] != '\0') {
1924 		attr = (struct fdmi_attr_s *) curr_ptr;
1925 		attr->type = cpu_to_be16(FDMI_PORT_ATTRIB_HOST_NAME);
1926 		templen = (u16) strlen(fcs_port_attr.host_name);
1927 		memcpy(attr->value, fcs_port_attr.host_name, templen);
1928 		templen = fc_roundup(templen, sizeof(u32));
1929 		curr_ptr += sizeof(attr->type) + sizeof(templen) + templen;
1930 		len += templen;
1931 		++count;
1932 		attr->len = cpu_to_be16(templen + sizeof(attr->type) +
1933 				sizeof(templen));
1934 	}
1935 
1936 	/*
1937 	 * Update size of payload
1938 	 */
1939 	port_attrib->attr_count = cpu_to_be32(count);
1940 	len += ((sizeof(attr->type) + sizeof(attr->len)) * count);
1941 	return len;
1942 }
1943 
1944 static          u16
bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)1945 bfa_fcs_lport_fdmi_build_rprt_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
1946 {
1947 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1948 	struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld;
1949 	u16        len;
1950 
1951 	rprt->hba_id = bfa_fcs_lport_get_pwwn(bfa_fcs_get_base_port(port->fcs));
1952 	rprt->port_name = bfa_fcs_lport_get_pwwn(port);
1953 
1954 	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
1955 				(u8 *) &rprt->port_attr_blk);
1956 
1957 	len += sizeof(rprt->hba_id) + sizeof(rprt->port_name);
1958 
1959 	return len;
1960 }
1961 
1962 static void
bfa_fcs_lport_fdmi_rprt_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)1963 bfa_fcs_lport_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
1964 				void *cbarg, bfa_status_t req_status,
1965 				u32 rsp_len, u32 resid_len,
1966 				struct fchs_s *rsp_fchs)
1967 {
1968 	struct bfa_fcs_lport_fdmi_s *fdmi =
1969 			(struct bfa_fcs_lport_fdmi_s *) cbarg;
1970 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
1971 	struct ct_hdr_s *cthdr = NULL;
1972 
1973 	bfa_trc(port->fcs, port->port_cfg.pwwn);
1974 
1975 	/*
1976 	 * Sanity Checks
1977 	 */
1978 	if (req_status != BFA_STATUS_OK) {
1979 		bfa_trc(port->fcs, req_status);
1980 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1981 		return;
1982 	}
1983 
1984 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
1985 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
1986 
1987 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
1988 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
1989 		return;
1990 	}
1991 
1992 	bfa_trc(port->fcs, cthdr->reason_code);
1993 	bfa_trc(port->fcs, cthdr->exp_code);
1994 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
1995 }
1996 
1997 /*
1998 *  RPA : Register Port Attributes.
1999  */
2000 static void
bfa_fcs_lport_fdmi_send_rpa(void * fdmi_cbarg,struct bfa_fcxp_s * fcxp_alloced)2001 bfa_fcs_lport_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2002 {
2003 	struct bfa_fcs_lport_fdmi_s *fdmi = fdmi_cbarg;
2004 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2005 	struct fchs_s fchs;
2006 	u16        len, attr_len;
2007 	struct bfa_fcxp_s *fcxp;
2008 	u8        *pyld;
2009 
2010 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2011 
2012 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2013 	if (!fcxp) {
2014 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe,
2015 					bfa_fcs_lport_fdmi_send_rpa, fdmi);
2016 		return;
2017 	}
2018 	fdmi->fcxp = fcxp;
2019 
2020 	pyld = bfa_fcxp_get_reqbuf(fcxp);
2021 	memset(pyld, 0, FC_MAX_PDUSZ);
2022 
2023 	len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_lport_get_fcid(port),
2024 				   FDMI_RPA);
2025 
2026 	attr_len = bfa_fcs_lport_fdmi_build_rpa_pyld(fdmi,
2027 				(u8 *) ((struct ct_hdr_s *) pyld + 1));
2028 
2029 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2030 			  FC_CLASS_3, len + attr_len, &fchs,
2031 			  bfa_fcs_lport_fdmi_rpa_response, (void *)fdmi,
2032 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2033 
2034 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT);
2035 }
2036 
2037 static          u16
bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s * fdmi,u8 * pyld)2038 bfa_fcs_lport_fdmi_build_rpa_pyld(struct bfa_fcs_lport_fdmi_s *fdmi, u8 *pyld)
2039 {
2040 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2041 	struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld;
2042 	u16        len;
2043 
2044 	rpa->port_name = bfa_fcs_lport_get_pwwn(port);
2045 
2046 	len = bfa_fcs_lport_fdmi_build_portattr_block(fdmi,
2047 				(u8 *) &rpa->port_attr_blk);
2048 
2049 	len += sizeof(rpa->port_name);
2050 
2051 	return len;
2052 }
2053 
2054 static void
bfa_fcs_lport_fdmi_rpa_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2055 bfa_fcs_lport_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2056 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2057 			u32 resid_len, struct fchs_s *rsp_fchs)
2058 {
2059 	struct bfa_fcs_lport_fdmi_s *fdmi =
2060 				(struct bfa_fcs_lport_fdmi_s *) cbarg;
2061 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2062 	struct ct_hdr_s *cthdr = NULL;
2063 
2064 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2065 
2066 	/*
2067 	 * Sanity Checks
2068 	 */
2069 	if (req_status != BFA_STATUS_OK) {
2070 		bfa_trc(port->fcs, req_status);
2071 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2072 		return;
2073 	}
2074 
2075 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2076 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2077 
2078 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2079 		bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK);
2080 		return;
2081 	}
2082 
2083 	bfa_trc(port->fcs, cthdr->reason_code);
2084 	bfa_trc(port->fcs, cthdr->exp_code);
2085 	bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR);
2086 }
2087 
2088 static void
bfa_fcs_lport_fdmi_timeout(void * arg)2089 bfa_fcs_lport_fdmi_timeout(void *arg)
2090 {
2091 	struct bfa_fcs_lport_fdmi_s *fdmi = (struct bfa_fcs_lport_fdmi_s *) arg;
2092 
2093 	bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT);
2094 }
2095 
2096 static void
bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s * fdmi,struct bfa_fcs_fdmi_hba_attr_s * hba_attr)2097 bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2098 			 struct bfa_fcs_fdmi_hba_attr_s *hba_attr)
2099 {
2100 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2101 	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2102 
2103 	memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s));
2104 
2105 	bfa_ioc_get_adapter_manufacturer(&port->fcs->bfa->ioc,
2106 					hba_attr->manufacturer);
2107 	bfa_ioc_get_adapter_serial_num(&port->fcs->bfa->ioc,
2108 					hba_attr->serial_num);
2109 	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2110 					hba_attr->model);
2111 	bfa_ioc_get_adapter_model(&port->fcs->bfa->ioc,
2112 					hba_attr->model_desc);
2113 	bfa_ioc_get_pci_chip_rev(&port->fcs->bfa->ioc,
2114 					hba_attr->hw_version);
2115 	bfa_ioc_get_adapter_optrom_ver(&port->fcs->bfa->ioc,
2116 					hba_attr->option_rom_ver);
2117 	bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc,
2118 					hba_attr->fw_version);
2119 
2120 	strncpy(hba_attr->driver_version, (char *)driver_info->version,
2121 		sizeof(hba_attr->driver_version));
2122 
2123 	strncpy(hba_attr->os_name, driver_info->host_os_name,
2124 		sizeof(hba_attr->os_name));
2125 
2126 	/*
2127 	 * If there is a patch level, append it
2128 	 * to the os name along with a separator
2129 	 */
2130 	if (driver_info->host_os_patch[0] != '\0') {
2131 		strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
2132 			sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR));
2133 		strncat(hba_attr->os_name, driver_info->host_os_patch,
2134 				sizeof(driver_info->host_os_patch));
2135 	}
2136 
2137 	hba_attr->max_ct_pyld = cpu_to_be32(FC_MAX_PDUSZ);
2138 }
2139 
2140 static void
bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s * fdmi,struct bfa_fcs_fdmi_port_attr_s * port_attr)2141 bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
2142 			  struct bfa_fcs_fdmi_port_attr_s *port_attr)
2143 {
2144 	struct bfa_fcs_lport_s *port = fdmi->ms->port;
2145 	struct bfa_fcs_driver_info_s  *driver_info = &port->fcs->driver_info;
2146 	struct bfa_port_attr_s pport_attr;
2147 
2148 	memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s));
2149 
2150 	/*
2151 	 * get pport attributes from hal
2152 	 */
2153 	bfa_fcport_get_attr(port->fcs->bfa, &pport_attr);
2154 
2155 	/*
2156 	 * get FC4 type Bitmask
2157 	 */
2158 	fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types);
2159 
2160 	/*
2161 	 * Supported Speeds
2162 	 */
2163 	port_attr->supp_speed = cpu_to_be32(BFA_FCS_FDMI_SUPORTED_SPEEDS);
2164 
2165 	/*
2166 	 * Current Speed
2167 	 */
2168 	port_attr->curr_speed = cpu_to_be32(pport_attr.speed);
2169 
2170 	/*
2171 	 * Max PDU Size.
2172 	 */
2173 	port_attr->max_frm_size = cpu_to_be32(FC_MAX_PDUSZ);
2174 
2175 	/*
2176 	 * OS device Name
2177 	 */
2178 	strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name,
2179 		sizeof(port_attr->os_device_name));
2180 
2181 	/*
2182 	 * Host name
2183 	 */
2184 	strncpy(port_attr->host_name, (char *)driver_info->host_machine_name,
2185 		sizeof(port_attr->host_name));
2186 
2187 }
2188 
2189 
2190 void
bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s * ms)2191 bfa_fcs_lport_fdmi_init(struct bfa_fcs_lport_ms_s *ms)
2192 {
2193 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2194 
2195 	fdmi->ms = ms;
2196 	if (ms->port->fcs->fdmi_enabled)
2197 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_offline);
2198 	else
2199 		bfa_sm_set_state(fdmi, bfa_fcs_lport_fdmi_sm_disabled);
2200 }
2201 
2202 void
bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s * ms)2203 bfa_fcs_lport_fdmi_offline(struct bfa_fcs_lport_ms_s *ms)
2204 {
2205 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2206 
2207 	fdmi->ms = ms;
2208 	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE);
2209 }
2210 
2211 void
bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s * ms)2212 bfa_fcs_lport_fdmi_online(struct bfa_fcs_lport_ms_s *ms)
2213 {
2214 	struct bfa_fcs_lport_fdmi_s *fdmi = &ms->fdmi;
2215 
2216 	fdmi->ms = ms;
2217 	bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE);
2218 }
2219 
2220 #define BFA_FCS_MS_CMD_MAX_RETRIES  2
2221 
2222 /*
2223  * forward declarations
2224  */
2225 static void     bfa_fcs_lport_ms_send_plogi(void *ms_cbarg,
2226 					   struct bfa_fcxp_s *fcxp_alloced);
2227 static void     bfa_fcs_lport_ms_timeout(void *arg);
2228 static void     bfa_fcs_lport_ms_plogi_response(void *fcsarg,
2229 					       struct bfa_fcxp_s *fcxp,
2230 					       void *cbarg,
2231 					       bfa_status_t req_status,
2232 					       u32 rsp_len,
2233 					       u32 resid_len,
2234 					       struct fchs_s *rsp_fchs);
2235 
2236 static void	bfa_fcs_lport_ms_send_gmal(void *ms_cbarg,
2237 					struct bfa_fcxp_s *fcxp_alloced);
2238 static void     bfa_fcs_lport_ms_gmal_response(void *fcsarg,
2239 					       struct bfa_fcxp_s *fcxp,
2240 					       void *cbarg,
2241 					       bfa_status_t req_status,
2242 					       u32 rsp_len,
2243 					       u32 resid_len,
2244 					       struct fchs_s *rsp_fchs);
2245 static void	bfa_fcs_lport_ms_send_gfn(void *ms_cbarg,
2246 					struct bfa_fcxp_s *fcxp_alloced);
2247 static void     bfa_fcs_lport_ms_gfn_response(void *fcsarg,
2248 					       struct bfa_fcxp_s *fcxp,
2249 					       void *cbarg,
2250 					       bfa_status_t req_status,
2251 					       u32 rsp_len,
2252 					       u32 resid_len,
2253 					       struct fchs_s *rsp_fchs);
2254 /*
2255  *  fcs_ms_sm FCS MS state machine
2256  */
2257 
2258 /*
2259  *  MS State Machine events
2260  */
2261 enum port_ms_event {
2262 	MSSM_EVENT_PORT_ONLINE = 1,
2263 	MSSM_EVENT_PORT_OFFLINE = 2,
2264 	MSSM_EVENT_RSP_OK = 3,
2265 	MSSM_EVENT_RSP_ERROR = 4,
2266 	MSSM_EVENT_TIMEOUT = 5,
2267 	MSSM_EVENT_FCXP_SENT = 6,
2268 	MSSM_EVENT_PORT_FABRIC_RSCN = 7
2269 };
2270 
2271 static void     bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2272 					   enum port_ms_event event);
2273 static void     bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2274 						 enum port_ms_event event);
2275 static void     bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2276 					 enum port_ms_event event);
2277 static void     bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2278 					       enum port_ms_event event);
2279 static void     bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2280 						 enum port_ms_event event);
2281 static void     bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2282 					 enum port_ms_event event);
2283 static void     bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2284 					       enum port_ms_event event);
2285 static void     bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2286 						 enum port_ms_event event);
2287 static void     bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2288 					 enum port_ms_event event);
2289 static void     bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2290 					       enum port_ms_event event);
2291 static void     bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2292 					  enum port_ms_event event);
2293 /*
2294  *	Start in offline state - awaiting NS to send start.
2295  */
2296 static void
bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2297 bfa_fcs_lport_ms_sm_offline(struct bfa_fcs_lport_ms_s *ms,
2298 				enum port_ms_event event)
2299 {
2300 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2301 	bfa_trc(ms->port->fcs, event);
2302 
2303 	switch (event) {
2304 	case MSSM_EVENT_PORT_ONLINE:
2305 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2306 		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2307 		break;
2308 
2309 	case MSSM_EVENT_PORT_OFFLINE:
2310 		break;
2311 
2312 	default:
2313 		bfa_sm_fault(ms->port->fcs, event);
2314 	}
2315 }
2316 
2317 static void
bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2318 bfa_fcs_lport_ms_sm_plogi_sending(struct bfa_fcs_lport_ms_s *ms,
2319 				enum port_ms_event event)
2320 {
2321 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2322 	bfa_trc(ms->port->fcs, event);
2323 
2324 	switch (event) {
2325 	case MSSM_EVENT_FCXP_SENT:
2326 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi);
2327 		break;
2328 
2329 	case MSSM_EVENT_PORT_OFFLINE:
2330 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2331 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2332 					   &ms->fcxp_wqe);
2333 		break;
2334 
2335 	default:
2336 		bfa_sm_fault(ms->port->fcs, event);
2337 	}
2338 }
2339 
2340 static void
bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2341 bfa_fcs_lport_ms_sm_plogi(struct bfa_fcs_lport_ms_s *ms,
2342 			enum port_ms_event event)
2343 {
2344 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2345 	bfa_trc(ms->port->fcs, event);
2346 
2347 	switch (event) {
2348 	case MSSM_EVENT_RSP_ERROR:
2349 		/*
2350 		 * Start timer for a delayed retry
2351 		 */
2352 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_retry);
2353 		ms->port->stats.ms_retries++;
2354 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2355 				    &ms->timer, bfa_fcs_lport_ms_timeout, ms,
2356 				    BFA_FCS_RETRY_TIMEOUT);
2357 		break;
2358 
2359 	case MSSM_EVENT_RSP_OK:
2360 		/*
2361 		 * since plogi is done, now invoke MS related sub-modules
2362 		 */
2363 		bfa_fcs_lport_fdmi_online(ms);
2364 
2365 		/*
2366 		 * if this is a Vport, go to online state.
2367 		 */
2368 		if (ms->port->vport) {
2369 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2370 			break;
2371 		}
2372 
2373 		/*
2374 		 * For a base port we need to get the
2375 		 * switch's IP address.
2376 		 */
2377 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2378 		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2379 		break;
2380 
2381 	case MSSM_EVENT_PORT_OFFLINE:
2382 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2383 		bfa_fcxp_discard(ms->fcxp);
2384 		break;
2385 
2386 	default:
2387 		bfa_sm_fault(ms->port->fcs, event);
2388 	}
2389 }
2390 
2391 static void
bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2392 bfa_fcs_lport_ms_sm_plogi_retry(struct bfa_fcs_lport_ms_s *ms,
2393 			enum port_ms_event event)
2394 {
2395 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2396 	bfa_trc(ms->port->fcs, event);
2397 
2398 	switch (event) {
2399 	case MSSM_EVENT_TIMEOUT:
2400 		/*
2401 		 * Retry Timer Expired. Re-send
2402 		 */
2403 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_plogi_sending);
2404 		bfa_fcs_lport_ms_send_plogi(ms, NULL);
2405 		break;
2406 
2407 	case MSSM_EVENT_PORT_OFFLINE:
2408 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2409 		bfa_timer_stop(&ms->timer);
2410 		break;
2411 
2412 	default:
2413 		bfa_sm_fault(ms->port->fcs, event);
2414 	}
2415 }
2416 
2417 static void
bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2418 bfa_fcs_lport_ms_sm_online(struct bfa_fcs_lport_ms_s *ms,
2419 			enum port_ms_event event)
2420 {
2421 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2422 	bfa_trc(ms->port->fcs, event);
2423 
2424 	switch (event) {
2425 	case MSSM_EVENT_PORT_OFFLINE:
2426 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2427 		break;
2428 
2429 	case MSSM_EVENT_PORT_FABRIC_RSCN:
2430 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2431 		ms->retry_cnt = 0;
2432 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2433 		break;
2434 
2435 	default:
2436 		bfa_sm_fault(ms->port->fcs, event);
2437 	}
2438 }
2439 
2440 static void
bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2441 bfa_fcs_lport_ms_sm_gmal_sending(struct bfa_fcs_lport_ms_s *ms,
2442 				enum port_ms_event event)
2443 {
2444 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2445 	bfa_trc(ms->port->fcs, event);
2446 
2447 	switch (event) {
2448 	case MSSM_EVENT_FCXP_SENT:
2449 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal);
2450 		break;
2451 
2452 	case MSSM_EVENT_PORT_OFFLINE:
2453 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2454 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2455 					   &ms->fcxp_wqe);
2456 		break;
2457 
2458 	default:
2459 		bfa_sm_fault(ms->port->fcs, event);
2460 	}
2461 }
2462 
2463 static void
bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2464 bfa_fcs_lport_ms_sm_gmal(struct bfa_fcs_lport_ms_s *ms,
2465 				enum port_ms_event event)
2466 {
2467 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2468 	bfa_trc(ms->port->fcs, event);
2469 
2470 	switch (event) {
2471 	case MSSM_EVENT_RSP_ERROR:
2472 		/*
2473 		 * Start timer for a delayed retry
2474 		 */
2475 		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2476 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_retry);
2477 			ms->port->stats.ms_retries++;
2478 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2479 				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
2480 				BFA_FCS_RETRY_TIMEOUT);
2481 		} else {
2482 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2483 			bfa_fcs_lport_ms_send_gfn(ms, NULL);
2484 			ms->retry_cnt = 0;
2485 		}
2486 		break;
2487 
2488 	case MSSM_EVENT_RSP_OK:
2489 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2490 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2491 		break;
2492 
2493 	case MSSM_EVENT_PORT_OFFLINE:
2494 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2495 		bfa_fcxp_discard(ms->fcxp);
2496 		break;
2497 
2498 	default:
2499 		bfa_sm_fault(ms->port->fcs, event);
2500 	}
2501 }
2502 
2503 static void
bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2504 bfa_fcs_lport_ms_sm_gmal_retry(struct bfa_fcs_lport_ms_s *ms,
2505 				enum port_ms_event event)
2506 {
2507 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2508 	bfa_trc(ms->port->fcs, event);
2509 
2510 	switch (event) {
2511 	case MSSM_EVENT_TIMEOUT:
2512 		/*
2513 		 * Retry Timer Expired. Re-send
2514 		 */
2515 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gmal_sending);
2516 		bfa_fcs_lport_ms_send_gmal(ms, NULL);
2517 		break;
2518 
2519 	case MSSM_EVENT_PORT_OFFLINE:
2520 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2521 		bfa_timer_stop(&ms->timer);
2522 		break;
2523 
2524 	default:
2525 		bfa_sm_fault(ms->port->fcs, event);
2526 	}
2527 }
2528 /*
2529  *  ms_pvt MS local functions
2530  */
2531 
2532 static void
bfa_fcs_lport_ms_send_gmal(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)2533 bfa_fcs_lport_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2534 {
2535 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2536 	bfa_fcs_lport_t *port = ms->port;
2537 	struct fchs_s	fchs;
2538 	int		len;
2539 	struct bfa_fcxp_s *fcxp;
2540 
2541 	bfa_trc(port->fcs, port->pid);
2542 
2543 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2544 	if (!fcxp) {
2545 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2546 					bfa_fcs_lport_ms_send_gmal, ms);
2547 		return;
2548 	}
2549 	ms->fcxp = fcxp;
2550 
2551 	len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2552 			     bfa_fcs_lport_get_fcid(port),
2553 				 port->fabric->lps->pr_nwwn);
2554 
2555 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2556 			  FC_CLASS_3, len, &fchs,
2557 			  bfa_fcs_lport_ms_gmal_response, (void *)ms,
2558 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2559 
2560 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2561 }
2562 
2563 static void
bfa_fcs_lport_ms_gmal_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2564 bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2565 				void *cbarg, bfa_status_t req_status,
2566 				u32 rsp_len, u32 resid_len,
2567 				struct fchs_s *rsp_fchs)
2568 {
2569 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2570 	bfa_fcs_lport_t *port = ms->port;
2571 	struct ct_hdr_s		*cthdr = NULL;
2572 	struct fcgs_gmal_resp_s *gmal_resp;
2573 	struct fcgs_gmal_entry_s *gmal_entry;
2574 	u32		num_entries;
2575 	u8			*rsp_str;
2576 
2577 	bfa_trc(port->fcs, req_status);
2578 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2579 
2580 	/*
2581 	 * Sanity Checks
2582 	 */
2583 	if (req_status != BFA_STATUS_OK) {
2584 		bfa_trc(port->fcs, req_status);
2585 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2586 		return;
2587 	}
2588 
2589 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2590 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2591 
2592 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2593 		gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1);
2594 
2595 		num_entries = be32_to_cpu(gmal_resp->ms_len);
2596 		if (num_entries == 0) {
2597 			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2598 			return;
2599 		}
2600 		/*
2601 		* The response could contain multiple Entries.
2602 		* Entries for SNMP interface, etc.
2603 		* We look for the entry with a telnet prefix.
2604 		* First "http://" entry refers to IP addr
2605 		*/
2606 
2607 		gmal_entry = (struct fcgs_gmal_entry_s *)gmal_resp->ms_ma;
2608 		while (num_entries > 0) {
2609 			if (strncmp(gmal_entry->prefix,
2610 				CT_GMAL_RESP_PREFIX_HTTP,
2611 				sizeof(gmal_entry->prefix)) == 0) {
2612 
2613 				/*
2614 				* if the IP address is terminating with a '/',
2615 				* remove it.
2616 				* Byte 0 consists of the length of the string.
2617 				*/
2618 				rsp_str = &(gmal_entry->prefix[0]);
2619 				if (rsp_str[gmal_entry->len-1] == '/')
2620 					rsp_str[gmal_entry->len-1] = 0;
2621 
2622 				/* copy IP Address to fabric */
2623 				strncpy(bfa_fcs_lport_get_fabric_ipaddr(port),
2624 					gmal_entry->ip_addr,
2625 					BFA_FCS_FABRIC_IPADDR_SZ);
2626 				break;
2627 			} else {
2628 				--num_entries;
2629 				++gmal_entry;
2630 			}
2631 		}
2632 
2633 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2634 		return;
2635 	}
2636 
2637 	bfa_trc(port->fcs, cthdr->reason_code);
2638 	bfa_trc(port->fcs, cthdr->exp_code);
2639 	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2640 }
2641 
2642 static void
bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2643 bfa_fcs_lport_ms_sm_gfn_sending(struct bfa_fcs_lport_ms_s *ms,
2644 			enum port_ms_event event)
2645 {
2646 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2647 	bfa_trc(ms->port->fcs, event);
2648 
2649 	switch (event) {
2650 	case MSSM_EVENT_FCXP_SENT:
2651 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn);
2652 		break;
2653 
2654 	case MSSM_EVENT_PORT_OFFLINE:
2655 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2656 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2657 					   &ms->fcxp_wqe);
2658 		break;
2659 
2660 	default:
2661 		bfa_sm_fault(ms->port->fcs, event);
2662 	}
2663 }
2664 
2665 static void
bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2666 bfa_fcs_lport_ms_sm_gfn(struct bfa_fcs_lport_ms_s *ms,
2667 			enum port_ms_event event)
2668 {
2669 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2670 	bfa_trc(ms->port->fcs, event);
2671 
2672 	switch (event) {
2673 	case MSSM_EVENT_RSP_ERROR:
2674 		/*
2675 		 * Start timer for a delayed retry
2676 		 */
2677 		if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) {
2678 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_retry);
2679 			ms->port->stats.ms_retries++;
2680 			bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port),
2681 				&ms->timer, bfa_fcs_lport_ms_timeout, ms,
2682 				BFA_FCS_RETRY_TIMEOUT);
2683 		} else {
2684 			bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2685 			ms->retry_cnt = 0;
2686 		}
2687 		break;
2688 
2689 	case MSSM_EVENT_RSP_OK:
2690 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_online);
2691 		break;
2692 
2693 	case MSSM_EVENT_PORT_OFFLINE:
2694 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2695 		bfa_fcxp_discard(ms->fcxp);
2696 		break;
2697 
2698 	default:
2699 		bfa_sm_fault(ms->port->fcs, event);
2700 	}
2701 }
2702 
2703 static void
bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s * ms,enum port_ms_event event)2704 bfa_fcs_lport_ms_sm_gfn_retry(struct bfa_fcs_lport_ms_s *ms,
2705 				enum port_ms_event event)
2706 {
2707 	bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn);
2708 	bfa_trc(ms->port->fcs, event);
2709 
2710 	switch (event) {
2711 	case MSSM_EVENT_TIMEOUT:
2712 		/*
2713 		 * Retry Timer Expired. Re-send
2714 		 */
2715 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_gfn_sending);
2716 		bfa_fcs_lport_ms_send_gfn(ms, NULL);
2717 		break;
2718 
2719 	case MSSM_EVENT_PORT_OFFLINE:
2720 		bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2721 		bfa_timer_stop(&ms->timer);
2722 		break;
2723 
2724 	default:
2725 		bfa_sm_fault(ms->port->fcs, event);
2726 	}
2727 }
2728 /*
2729  *  ms_pvt MS local functions
2730  */
2731 
2732 static void
bfa_fcs_lport_ms_send_gfn(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)2733 bfa_fcs_lport_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2734 {
2735 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2736 	bfa_fcs_lport_t *port = ms->port;
2737 	struct fchs_s		fchs;
2738 	int			len;
2739 	struct bfa_fcxp_s *fcxp;
2740 
2741 	bfa_trc(port->fcs, port->pid);
2742 
2743 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2744 	if (!fcxp) {
2745 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2746 					bfa_fcs_lport_ms_send_gfn, ms);
2747 		return;
2748 	}
2749 	ms->fcxp = fcxp;
2750 
2751 	len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2752 			     bfa_fcs_lport_get_fcid(port),
2753 				 port->fabric->lps->pr_nwwn);
2754 
2755 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2756 			  FC_CLASS_3, len, &fchs,
2757 			  bfa_fcs_lport_ms_gfn_response, (void *)ms,
2758 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
2759 
2760 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2761 }
2762 
2763 static void
bfa_fcs_lport_ms_gfn_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2764 bfa_fcs_lport_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2765 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
2766 			u32 resid_len, struct fchs_s *rsp_fchs)
2767 {
2768 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2769 	bfa_fcs_lport_t *port = ms->port;
2770 	struct ct_hdr_s	*cthdr = NULL;
2771 	wwn_t	       *gfn_resp;
2772 
2773 	bfa_trc(port->fcs, req_status);
2774 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2775 
2776 	/*
2777 	 * Sanity Checks
2778 	 */
2779 	if (req_status != BFA_STATUS_OK) {
2780 		bfa_trc(port->fcs, req_status);
2781 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2782 		return;
2783 	}
2784 
2785 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
2786 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
2787 
2788 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
2789 		gfn_resp = (wwn_t *)(cthdr + 1);
2790 		/* check if it has actually changed */
2791 		if ((memcmp((void *)&bfa_fcs_lport_get_fabric_name(port),
2792 				gfn_resp, sizeof(wwn_t)) != 0)) {
2793 			bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp);
2794 		}
2795 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2796 		return;
2797 	}
2798 
2799 	bfa_trc(port->fcs, cthdr->reason_code);
2800 	bfa_trc(port->fcs, cthdr->exp_code);
2801 	bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2802 }
2803 
2804 /*
2805  *  ms_pvt MS local functions
2806  */
2807 
2808 static void
bfa_fcs_lport_ms_send_plogi(void * ms_cbarg,struct bfa_fcxp_s * fcxp_alloced)2809 bfa_fcs_lport_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced)
2810 {
2811 	struct bfa_fcs_lport_ms_s *ms = ms_cbarg;
2812 	struct bfa_fcs_lport_s *port = ms->port;
2813 	struct fchs_s	fchs;
2814 	int	len;
2815 	struct bfa_fcxp_s *fcxp;
2816 
2817 	bfa_trc(port->fcs, port->pid);
2818 
2819 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
2820 	if (!fcxp) {
2821 		port->stats.ms_plogi_alloc_wait++;
2822 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe,
2823 					bfa_fcs_lport_ms_send_plogi, ms);
2824 		return;
2825 	}
2826 	ms->fcxp = fcxp;
2827 
2828 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
2829 			     bfa_hton3b(FC_MGMT_SERVER),
2830 			     bfa_fcs_lport_get_fcid(port), 0,
2831 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
2832 				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
2833 
2834 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
2835 			  FC_CLASS_3, len, &fchs,
2836 			  bfa_fcs_lport_ms_plogi_response, (void *)ms,
2837 			  FC_MAX_PDUSZ, FC_ELS_TOV);
2838 
2839 	port->stats.ms_plogi_sent++;
2840 	bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT);
2841 }
2842 
2843 static void
bfa_fcs_lport_ms_plogi_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)2844 bfa_fcs_lport_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
2845 			void *cbarg, bfa_status_t req_status,
2846 			u32 rsp_len, u32 resid_len, struct fchs_s *rsp_fchs)
2847 {
2848 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) cbarg;
2849 	struct bfa_fcs_lport_s *port = ms->port;
2850 	struct fc_els_cmd_s *els_cmd;
2851 	struct fc_ls_rjt_s *ls_rjt;
2852 
2853 	bfa_trc(port->fcs, req_status);
2854 	bfa_trc(port->fcs, port->port_cfg.pwwn);
2855 
2856 	/*
2857 	 * Sanity Checks
2858 	 */
2859 	if (req_status != BFA_STATUS_OK) {
2860 		port->stats.ms_plogi_rsp_err++;
2861 		bfa_trc(port->fcs, req_status);
2862 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2863 		return;
2864 	}
2865 
2866 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
2867 
2868 	switch (els_cmd->els_code) {
2869 
2870 	case FC_ELS_ACC:
2871 		if (rsp_len < sizeof(struct fc_logi_s)) {
2872 			bfa_trc(port->fcs, rsp_len);
2873 			port->stats.ms_plogi_acc_err++;
2874 			bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2875 			break;
2876 		}
2877 		port->stats.ms_plogi_accepts++;
2878 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK);
2879 		break;
2880 
2881 	case FC_ELS_LS_RJT:
2882 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
2883 
2884 		bfa_trc(port->fcs, ls_rjt->reason_code);
2885 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
2886 
2887 		port->stats.ms_rejects++;
2888 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2889 		break;
2890 
2891 	default:
2892 		port->stats.ms_plogi_unknown_rsp++;
2893 		bfa_trc(port->fcs, els_cmd->els_code);
2894 		bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR);
2895 	}
2896 }
2897 
2898 static void
bfa_fcs_lport_ms_timeout(void * arg)2899 bfa_fcs_lport_ms_timeout(void *arg)
2900 {
2901 	struct bfa_fcs_lport_ms_s *ms = (struct bfa_fcs_lport_ms_s *) arg;
2902 
2903 	ms->port->stats.ms_timeouts++;
2904 	bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT);
2905 }
2906 
2907 
2908 void
bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s * port)2909 bfa_fcs_lport_ms_init(struct bfa_fcs_lport_s *port)
2910 {
2911 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2912 
2913 	ms->port = port;
2914 	bfa_sm_set_state(ms, bfa_fcs_lport_ms_sm_offline);
2915 
2916 	/*
2917 	 * Invoke init routines of sub modules.
2918 	 */
2919 	bfa_fcs_lport_fdmi_init(ms);
2920 }
2921 
2922 void
bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s * port)2923 bfa_fcs_lport_ms_offline(struct bfa_fcs_lport_s *port)
2924 {
2925 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2926 
2927 	ms->port = port;
2928 	bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE);
2929 	bfa_fcs_lport_fdmi_offline(ms);
2930 }
2931 
2932 void
bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s * port)2933 bfa_fcs_lport_ms_online(struct bfa_fcs_lport_s *port)
2934 {
2935 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2936 
2937 	ms->port = port;
2938 	bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE);
2939 }
2940 void
bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s * port)2941 bfa_fcs_lport_ms_fabric_rscn(struct bfa_fcs_lport_s *port)
2942 {
2943 	struct bfa_fcs_lport_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port);
2944 
2945 	/* todo.  Handle this only  when in Online state */
2946 	if (bfa_sm_cmp_state(ms, bfa_fcs_lport_ms_sm_online))
2947 		bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN);
2948 }
2949 
2950 /*
2951  * @page ns_sm_info VPORT NS State Machine
2952  *
2953  * @section ns_sm_interactions VPORT NS State Machine Interactions
2954  *
2955  * @section ns_sm VPORT NS State Machine
2956  * img ns_sm.jpg
2957  */
2958 
2959 /*
2960  * forward declarations
2961  */
2962 static void     bfa_fcs_lport_ns_send_plogi(void *ns_cbarg,
2963 					   struct bfa_fcxp_s *fcxp_alloced);
2964 static void     bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg,
2965 					     struct bfa_fcxp_s *fcxp_alloced);
2966 static void     bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg,
2967 					    struct bfa_fcxp_s *fcxp_alloced);
2968 static void     bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg,
2969 					    struct bfa_fcxp_s *fcxp_alloced);
2970 static void     bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg,
2971 					    struct bfa_fcxp_s *fcxp_alloced);
2972 static void     bfa_fcs_lport_ns_timeout(void *arg);
2973 static void     bfa_fcs_lport_ns_plogi_response(void *fcsarg,
2974 					       struct bfa_fcxp_s *fcxp,
2975 					       void *cbarg,
2976 					       bfa_status_t req_status,
2977 					       u32 rsp_len,
2978 					       u32 resid_len,
2979 					       struct fchs_s *rsp_fchs);
2980 static void     bfa_fcs_lport_ns_rspn_id_response(void *fcsarg,
2981 						 struct bfa_fcxp_s *fcxp,
2982 						 void *cbarg,
2983 						 bfa_status_t req_status,
2984 						 u32 rsp_len,
2985 						 u32 resid_len,
2986 						 struct fchs_s *rsp_fchs);
2987 static void     bfa_fcs_lport_ns_rft_id_response(void *fcsarg,
2988 						struct bfa_fcxp_s *fcxp,
2989 						void *cbarg,
2990 						bfa_status_t req_status,
2991 						u32 rsp_len,
2992 						u32 resid_len,
2993 						struct fchs_s *rsp_fchs);
2994 static void     bfa_fcs_lport_ns_rff_id_response(void *fcsarg,
2995 						struct bfa_fcxp_s *fcxp,
2996 						void *cbarg,
2997 						bfa_status_t req_status,
2998 						u32 rsp_len,
2999 						u32 resid_len,
3000 						struct fchs_s *rsp_fchs);
3001 static void     bfa_fcs_lport_ns_gid_ft_response(void *fcsarg,
3002 						struct bfa_fcxp_s *fcxp,
3003 						void *cbarg,
3004 						bfa_status_t req_status,
3005 						u32 rsp_len,
3006 						u32 resid_len,
3007 						struct fchs_s *rsp_fchs);
3008 static void     bfa_fcs_lport_ns_process_gidft_pids(
3009 				struct bfa_fcs_lport_s *port,
3010 				u32 *pid_buf, u32 n_pids);
3011 
3012 static void bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port);
3013 /*
3014  *  fcs_ns_sm FCS nameserver interface state machine
3015  */
3016 
3017 /*
3018  * VPort NS State Machine events
3019  */
3020 enum vport_ns_event {
3021 	NSSM_EVENT_PORT_ONLINE = 1,
3022 	NSSM_EVENT_PORT_OFFLINE = 2,
3023 	NSSM_EVENT_PLOGI_SENT = 3,
3024 	NSSM_EVENT_RSP_OK = 4,
3025 	NSSM_EVENT_RSP_ERROR = 5,
3026 	NSSM_EVENT_TIMEOUT = 6,
3027 	NSSM_EVENT_NS_QUERY = 7,
3028 	NSSM_EVENT_RSPNID_SENT = 8,
3029 	NSSM_EVENT_RFTID_SENT = 9,
3030 	NSSM_EVENT_RFFID_SENT = 10,
3031 	NSSM_EVENT_GIDFT_SENT = 11,
3032 };
3033 
3034 static void     bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3035 					   enum vport_ns_event event);
3036 static void     bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3037 						 enum vport_ns_event event);
3038 static void     bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3039 					 enum vport_ns_event event);
3040 static void     bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3041 					       enum vport_ns_event event);
3042 static void     bfa_fcs_lport_ns_sm_sending_rspn_id(
3043 					struct bfa_fcs_lport_ns_s *ns,
3044 					enum vport_ns_event event);
3045 static void     bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3046 					   enum vport_ns_event event);
3047 static void     bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3048 						 enum vport_ns_event event);
3049 static void     bfa_fcs_lport_ns_sm_sending_rft_id(
3050 					struct bfa_fcs_lport_ns_s *ns,
3051 					enum vport_ns_event event);
3052 static void     bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3053 						enum vport_ns_event event);
3054 static void     bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3055 					  enum vport_ns_event event);
3056 static void     bfa_fcs_lport_ns_sm_sending_rff_id(
3057 					struct bfa_fcs_lport_ns_s *ns,
3058 					enum vport_ns_event event);
3059 static void     bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3060 						enum vport_ns_event event);
3061 static void     bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3062 					  enum vport_ns_event event);
3063 static void     bfa_fcs_lport_ns_sm_sending_gid_ft(
3064 					struct bfa_fcs_lport_ns_s *ns,
3065 					enum vport_ns_event event);
3066 static void     bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3067 					  enum vport_ns_event event);
3068 static void     bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3069 						enum vport_ns_event event);
3070 static void     bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3071 					  enum vport_ns_event event);
3072 /*
3073  *	Start in offline state - awaiting linkup
3074  */
3075 static void
bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3076 bfa_fcs_lport_ns_sm_offline(struct bfa_fcs_lport_ns_s *ns,
3077 			enum vport_ns_event event)
3078 {
3079 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3080 	bfa_trc(ns->port->fcs, event);
3081 
3082 	switch (event) {
3083 	case NSSM_EVENT_PORT_ONLINE:
3084 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3085 		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3086 		break;
3087 
3088 	case NSSM_EVENT_PORT_OFFLINE:
3089 		break;
3090 
3091 	default:
3092 		bfa_sm_fault(ns->port->fcs, event);
3093 	}
3094 }
3095 
3096 static void
bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3097 bfa_fcs_lport_ns_sm_plogi_sending(struct bfa_fcs_lport_ns_s *ns,
3098 			enum vport_ns_event event)
3099 {
3100 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3101 	bfa_trc(ns->port->fcs, event);
3102 
3103 	switch (event) {
3104 	case NSSM_EVENT_PLOGI_SENT:
3105 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi);
3106 		break;
3107 
3108 	case NSSM_EVENT_PORT_OFFLINE:
3109 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3110 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3111 					   &ns->fcxp_wqe);
3112 		break;
3113 
3114 	default:
3115 		bfa_sm_fault(ns->port->fcs, event);
3116 	}
3117 }
3118 
3119 static void
bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3120 bfa_fcs_lport_ns_sm_plogi(struct bfa_fcs_lport_ns_s *ns,
3121 			enum vport_ns_event event)
3122 {
3123 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3124 	bfa_trc(ns->port->fcs, event);
3125 
3126 	switch (event) {
3127 	case NSSM_EVENT_RSP_ERROR:
3128 		/*
3129 		 * Start timer for a delayed retry
3130 		 */
3131 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_retry);
3132 		ns->port->stats.ns_retries++;
3133 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3134 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3135 				    BFA_FCS_RETRY_TIMEOUT);
3136 		break;
3137 
3138 	case NSSM_EVENT_RSP_OK:
3139 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3140 		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3141 		break;
3142 
3143 	case NSSM_EVENT_PORT_OFFLINE:
3144 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3145 		bfa_fcxp_discard(ns->fcxp);
3146 		break;
3147 
3148 	default:
3149 		bfa_sm_fault(ns->port->fcs, event);
3150 	}
3151 }
3152 
3153 static void
bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3154 bfa_fcs_lport_ns_sm_plogi_retry(struct bfa_fcs_lport_ns_s *ns,
3155 				enum vport_ns_event event)
3156 {
3157 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3158 	bfa_trc(ns->port->fcs, event);
3159 
3160 	switch (event) {
3161 	case NSSM_EVENT_TIMEOUT:
3162 		/*
3163 		 * Retry Timer Expired. Re-send
3164 		 */
3165 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_plogi_sending);
3166 		bfa_fcs_lport_ns_send_plogi(ns, NULL);
3167 		break;
3168 
3169 	case NSSM_EVENT_PORT_OFFLINE:
3170 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3171 		bfa_timer_stop(&ns->timer);
3172 		break;
3173 
3174 	default:
3175 		bfa_sm_fault(ns->port->fcs, event);
3176 	}
3177 }
3178 
3179 static void
bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3180 bfa_fcs_lport_ns_sm_sending_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3181 				   enum vport_ns_event event)
3182 {
3183 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3184 	bfa_trc(ns->port->fcs, event);
3185 
3186 	switch (event) {
3187 	case NSSM_EVENT_RSPNID_SENT:
3188 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id);
3189 		break;
3190 
3191 	case NSSM_EVENT_PORT_OFFLINE:
3192 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3193 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3194 					   &ns->fcxp_wqe);
3195 		break;
3196 
3197 	default:
3198 		bfa_sm_fault(ns->port->fcs, event);
3199 	}
3200 }
3201 
3202 static void
bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3203 bfa_fcs_lport_ns_sm_rspn_id(struct bfa_fcs_lport_ns_s *ns,
3204 			enum vport_ns_event event)
3205 {
3206 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3207 	bfa_trc(ns->port->fcs, event);
3208 
3209 	switch (event) {
3210 	case NSSM_EVENT_RSP_ERROR:
3211 		/*
3212 		 * Start timer for a delayed retry
3213 		 */
3214 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rspn_id_retry);
3215 		ns->port->stats.ns_retries++;
3216 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3217 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3218 				    BFA_FCS_RETRY_TIMEOUT);
3219 		break;
3220 
3221 	case NSSM_EVENT_RSP_OK:
3222 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3223 		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3224 		break;
3225 
3226 	case NSSM_EVENT_PORT_OFFLINE:
3227 		bfa_fcxp_discard(ns->fcxp);
3228 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3229 		break;
3230 
3231 	default:
3232 		bfa_sm_fault(ns->port->fcs, event);
3233 	}
3234 }
3235 
3236 static void
bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3237 bfa_fcs_lport_ns_sm_rspn_id_retry(struct bfa_fcs_lport_ns_s *ns,
3238 				enum vport_ns_event event)
3239 {
3240 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3241 	bfa_trc(ns->port->fcs, event);
3242 
3243 	switch (event) {
3244 	case NSSM_EVENT_TIMEOUT:
3245 		/*
3246 		 * Retry Timer Expired. Re-send
3247 		 */
3248 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rspn_id);
3249 		bfa_fcs_lport_ns_send_rspn_id(ns, NULL);
3250 		break;
3251 
3252 	case NSSM_EVENT_PORT_OFFLINE:
3253 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3254 		bfa_timer_stop(&ns->timer);
3255 		break;
3256 
3257 	default:
3258 		bfa_sm_fault(ns->port->fcs, event);
3259 	}
3260 }
3261 
3262 static void
bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3263 bfa_fcs_lport_ns_sm_sending_rft_id(struct bfa_fcs_lport_ns_s *ns,
3264 				  enum vport_ns_event event)
3265 {
3266 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3267 	bfa_trc(ns->port->fcs, event);
3268 
3269 	switch (event) {
3270 	case NSSM_EVENT_RFTID_SENT:
3271 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id);
3272 		break;
3273 
3274 	case NSSM_EVENT_PORT_OFFLINE:
3275 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3276 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3277 					   &ns->fcxp_wqe);
3278 		break;
3279 
3280 	default:
3281 		bfa_sm_fault(ns->port->fcs, event);
3282 	}
3283 }
3284 
3285 static void
bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3286 bfa_fcs_lport_ns_sm_rft_id(struct bfa_fcs_lport_ns_s *ns,
3287 			enum vport_ns_event event)
3288 {
3289 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3290 	bfa_trc(ns->port->fcs, event);
3291 
3292 	switch (event) {
3293 	case NSSM_EVENT_RSP_OK:
3294 		/* Now move to register FC4 Features */
3295 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3296 		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3297 		break;
3298 
3299 	case NSSM_EVENT_RSP_ERROR:
3300 		/*
3301 		 * Start timer for a delayed retry
3302 		 */
3303 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rft_id_retry);
3304 		ns->port->stats.ns_retries++;
3305 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3306 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3307 				    BFA_FCS_RETRY_TIMEOUT);
3308 		break;
3309 
3310 	case NSSM_EVENT_PORT_OFFLINE:
3311 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3312 		bfa_fcxp_discard(ns->fcxp);
3313 		break;
3314 
3315 	default:
3316 		bfa_sm_fault(ns->port->fcs, event);
3317 	}
3318 }
3319 
3320 static void
bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3321 bfa_fcs_lport_ns_sm_rft_id_retry(struct bfa_fcs_lport_ns_s *ns,
3322 				enum vport_ns_event event)
3323 {
3324 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3325 	bfa_trc(ns->port->fcs, event);
3326 
3327 	switch (event) {
3328 	case NSSM_EVENT_TIMEOUT:
3329 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rft_id);
3330 		bfa_fcs_lport_ns_send_rft_id(ns, NULL);
3331 		break;
3332 
3333 	case NSSM_EVENT_PORT_OFFLINE:
3334 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3335 		bfa_timer_stop(&ns->timer);
3336 		break;
3337 
3338 	default:
3339 		bfa_sm_fault(ns->port->fcs, event);
3340 	}
3341 }
3342 
3343 static void
bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3344 bfa_fcs_lport_ns_sm_sending_rff_id(struct bfa_fcs_lport_ns_s *ns,
3345 				  enum vport_ns_event event)
3346 {
3347 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3348 	bfa_trc(ns->port->fcs, event);
3349 
3350 	switch (event) {
3351 	case NSSM_EVENT_RFFID_SENT:
3352 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id);
3353 		break;
3354 
3355 	case NSSM_EVENT_PORT_OFFLINE:
3356 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3357 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3358 					   &ns->fcxp_wqe);
3359 		break;
3360 
3361 	default:
3362 		bfa_sm_fault(ns->port->fcs, event);
3363 	}
3364 }
3365 
3366 static void
bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3367 bfa_fcs_lport_ns_sm_rff_id(struct bfa_fcs_lport_ns_s *ns,
3368 			enum vport_ns_event event)
3369 {
3370 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3371 	bfa_trc(ns->port->fcs, event);
3372 
3373 	switch (event) {
3374 	case NSSM_EVENT_RSP_OK:
3375 
3376 		/*
3377 		 * If min cfg mode is enabled, we donot initiate rport
3378 		 * discovery with the fabric. Instead, we will retrieve the
3379 		 * boot targets from HAL/FW.
3380 		 */
3381 		if (__fcs_min_cfg(ns->port->fcs)) {
3382 			bfa_fcs_lport_ns_boot_target_disc(ns->port);
3383 			bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3384 			return;
3385 		}
3386 
3387 		/*
3388 		 * If the port role is Initiator Mode issue NS query.
3389 		 * If it is Target Mode, skip this and go to online.
3390 		 */
3391 		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3392 			bfa_sm_set_state(ns,
3393 				bfa_fcs_lport_ns_sm_sending_gid_ft);
3394 			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3395 		}
3396 		/*
3397 		 * kick off mgmt srvr state machine
3398 		 */
3399 		bfa_fcs_lport_ms_online(ns->port);
3400 		break;
3401 
3402 	case NSSM_EVENT_RSP_ERROR:
3403 		/*
3404 		 * Start timer for a delayed retry
3405 		 */
3406 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_rff_id_retry);
3407 		ns->port->stats.ns_retries++;
3408 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3409 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3410 				    BFA_FCS_RETRY_TIMEOUT);
3411 		break;
3412 
3413 	case NSSM_EVENT_PORT_OFFLINE:
3414 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3415 		bfa_fcxp_discard(ns->fcxp);
3416 		break;
3417 
3418 	default:
3419 		bfa_sm_fault(ns->port->fcs, event);
3420 	}
3421 }
3422 
3423 static void
bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3424 bfa_fcs_lport_ns_sm_rff_id_retry(struct bfa_fcs_lport_ns_s *ns,
3425 				enum vport_ns_event event)
3426 {
3427 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3428 	bfa_trc(ns->port->fcs, event);
3429 
3430 	switch (event) {
3431 	case NSSM_EVENT_TIMEOUT:
3432 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_rff_id);
3433 		bfa_fcs_lport_ns_send_rff_id(ns, NULL);
3434 		break;
3435 
3436 	case NSSM_EVENT_PORT_OFFLINE:
3437 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3438 		bfa_timer_stop(&ns->timer);
3439 		break;
3440 
3441 	default:
3442 		bfa_sm_fault(ns->port->fcs, event);
3443 	}
3444 }
3445 static void
bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3446 bfa_fcs_lport_ns_sm_sending_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3447 				  enum vport_ns_event event)
3448 {
3449 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3450 	bfa_trc(ns->port->fcs, event);
3451 
3452 	switch (event) {
3453 	case NSSM_EVENT_GIDFT_SENT:
3454 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft);
3455 		break;
3456 
3457 	case NSSM_EVENT_PORT_OFFLINE:
3458 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3459 		bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3460 					   &ns->fcxp_wqe);
3461 		break;
3462 
3463 	default:
3464 		bfa_sm_fault(ns->port->fcs, event);
3465 	}
3466 }
3467 
3468 static void
bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3469 bfa_fcs_lport_ns_sm_gid_ft(struct bfa_fcs_lport_ns_s *ns,
3470 			enum vport_ns_event event)
3471 {
3472 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3473 	bfa_trc(ns->port->fcs, event);
3474 
3475 	switch (event) {
3476 	case NSSM_EVENT_RSP_OK:
3477 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_online);
3478 		break;
3479 
3480 	case NSSM_EVENT_RSP_ERROR:
3481 		/*
3482 		 * TBD: for certain reject codes, we don't need to retry
3483 		 */
3484 		/*
3485 		 * Start timer for a delayed retry
3486 		 */
3487 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_gid_ft_retry);
3488 		ns->port->stats.ns_retries++;
3489 		bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port),
3490 				    &ns->timer, bfa_fcs_lport_ns_timeout, ns,
3491 				    BFA_FCS_RETRY_TIMEOUT);
3492 		break;
3493 
3494 	case NSSM_EVENT_PORT_OFFLINE:
3495 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3496 		bfa_fcxp_discard(ns->fcxp);
3497 		break;
3498 
3499 	case  NSSM_EVENT_NS_QUERY:
3500 		break;
3501 
3502 	default:
3503 		bfa_sm_fault(ns->port->fcs, event);
3504 	}
3505 }
3506 
3507 static void
bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3508 bfa_fcs_lport_ns_sm_gid_ft_retry(struct bfa_fcs_lport_ns_s *ns,
3509 				enum vport_ns_event event)
3510 {
3511 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3512 	bfa_trc(ns->port->fcs, event);
3513 
3514 	switch (event) {
3515 	case NSSM_EVENT_TIMEOUT:
3516 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_sending_gid_ft);
3517 		bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3518 		break;
3519 
3520 	case NSSM_EVENT_PORT_OFFLINE:
3521 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3522 		bfa_timer_stop(&ns->timer);
3523 		break;
3524 
3525 	default:
3526 		bfa_sm_fault(ns->port->fcs, event);
3527 	}
3528 }
3529 
3530 static void
bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s * ns,enum vport_ns_event event)3531 bfa_fcs_lport_ns_sm_online(struct bfa_fcs_lport_ns_s *ns,
3532 			enum vport_ns_event event)
3533 {
3534 	bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn);
3535 	bfa_trc(ns->port->fcs, event);
3536 
3537 	switch (event) {
3538 	case NSSM_EVENT_PORT_OFFLINE:
3539 		bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
3540 		break;
3541 
3542 	case NSSM_EVENT_NS_QUERY:
3543 		/*
3544 		 * If the port role is Initiator Mode issue NS query.
3545 		 * If it is Target Mode, skip this and go to online.
3546 		 */
3547 		if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) {
3548 			bfa_sm_set_state(ns,
3549 				bfa_fcs_lport_ns_sm_sending_gid_ft);
3550 			bfa_fcs_lport_ns_send_gid_ft(ns, NULL);
3551 		};
3552 		break;
3553 
3554 	default:
3555 		bfa_sm_fault(ns->port->fcs, event);
3556 	}
3557 }
3558 
3559 
3560 
3561 /*
3562  *  ns_pvt Nameserver local functions
3563  */
3564 
3565 static void
bfa_fcs_lport_ns_send_plogi(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3566 bfa_fcs_lport_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3567 {
3568 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3569 	struct bfa_fcs_lport_s *port = ns->port;
3570 	struct fchs_s fchs;
3571 	int             len;
3572 	struct bfa_fcxp_s *fcxp;
3573 
3574 	bfa_trc(port->fcs, port->pid);
3575 
3576 fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3577 	if (!fcxp) {
3578 		port->stats.ns_plogi_alloc_wait++;
3579 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3580 					bfa_fcs_lport_ns_send_plogi, ns);
3581 		return;
3582 	}
3583 	ns->fcxp = fcxp;
3584 
3585 	len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3586 			     bfa_hton3b(FC_NAME_SERVER),
3587 			     bfa_fcs_lport_get_fcid(port), 0,
3588 			     port->port_cfg.pwwn, port->port_cfg.nwwn,
3589 				 bfa_fcport_get_maxfrsize(port->fcs->bfa));
3590 
3591 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3592 			  FC_CLASS_3, len, &fchs,
3593 			  bfa_fcs_lport_ns_plogi_response, (void *)ns,
3594 			  FC_MAX_PDUSZ, FC_ELS_TOV);
3595 	port->stats.ns_plogi_sent++;
3596 
3597 	bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT);
3598 }
3599 
3600 static void
bfa_fcs_lport_ns_plogi_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3601 bfa_fcs_lport_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3602 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
3603 		       u32 resid_len, struct fchs_s *rsp_fchs)
3604 {
3605 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3606 	struct bfa_fcs_lport_s *port = ns->port;
3607 	/* struct fc_logi_s *plogi_resp; */
3608 	struct fc_els_cmd_s *els_cmd;
3609 	struct fc_ls_rjt_s *ls_rjt;
3610 
3611 	bfa_trc(port->fcs, req_status);
3612 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3613 
3614 	/*
3615 	 * Sanity Checks
3616 	 */
3617 	if (req_status != BFA_STATUS_OK) {
3618 		bfa_trc(port->fcs, req_status);
3619 		port->stats.ns_plogi_rsp_err++;
3620 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3621 		return;
3622 	}
3623 
3624 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
3625 
3626 	switch (els_cmd->els_code) {
3627 
3628 	case FC_ELS_ACC:
3629 		if (rsp_len < sizeof(struct fc_logi_s)) {
3630 			bfa_trc(port->fcs, rsp_len);
3631 			port->stats.ns_plogi_acc_err++;
3632 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3633 			break;
3634 		}
3635 		port->stats.ns_plogi_accepts++;
3636 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3637 		break;
3638 
3639 	case FC_ELS_LS_RJT:
3640 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
3641 
3642 		bfa_trc(port->fcs, ls_rjt->reason_code);
3643 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
3644 
3645 		port->stats.ns_rejects++;
3646 
3647 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3648 		break;
3649 
3650 	default:
3651 		port->stats.ns_plogi_unknown_rsp++;
3652 		bfa_trc(port->fcs, els_cmd->els_code);
3653 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3654 	}
3655 }
3656 
3657 /*
3658  * Register the symbolic port name.
3659  */
3660 static void
bfa_fcs_lport_ns_send_rspn_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3661 bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3662 {
3663 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3664 	struct bfa_fcs_lport_s *port = ns->port;
3665 	struct fchs_s fchs;
3666 	int             len;
3667 	struct bfa_fcxp_s *fcxp;
3668 	u8         symbl[256];
3669 	u8         *psymbl = &symbl[0];
3670 
3671 	memset(symbl, 0, sizeof(symbl));
3672 
3673 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3674 
3675 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3676 	if (!fcxp) {
3677 		port->stats.ns_rspnid_alloc_wait++;
3678 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3679 					bfa_fcs_lport_ns_send_rspn_id, ns);
3680 		return;
3681 	}
3682 	ns->fcxp = fcxp;
3683 
3684 	/*
3685 	 * for V-Port, form a Port Symbolic Name
3686 	 */
3687 	if (port->vport) {
3688 		/*
3689 		 * For Vports, we append the vport's port symbolic name
3690 		 * to that of the base port.
3691 		 */
3692 
3693 		strncpy((char *)psymbl,
3694 			(char *) &
3695 			(bfa_fcs_lport_get_psym_name
3696 			 (bfa_fcs_get_base_port(port->fcs))),
3697 			strlen((char *) &
3698 			       bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3699 							  (port->fcs))));
3700 
3701 		/* Ensure we have a null terminating string. */
3702 		((char *)psymbl)[strlen((char *) &
3703 			bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port
3704 						(port->fcs)))] = 0;
3705 		strncat((char *)psymbl,
3706 			(char *) &(bfa_fcs_lport_get_psym_name(port)),
3707 		strlen((char *) &bfa_fcs_lport_get_psym_name(port)));
3708 	} else {
3709 		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
3710 	}
3711 
3712 	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3713 			      bfa_fcs_lport_get_fcid(port), 0, psymbl);
3714 
3715 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3716 			  FC_CLASS_3, len, &fchs,
3717 			  bfa_fcs_lport_ns_rspn_id_response, (void *)ns,
3718 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3719 
3720 	port->stats.ns_rspnid_sent++;
3721 
3722 	bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT);
3723 }
3724 
3725 static void
bfa_fcs_lport_ns_rspn_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3726 bfa_fcs_lport_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3727 				 void *cbarg, bfa_status_t req_status,
3728 				 u32 rsp_len, u32 resid_len,
3729 				 struct fchs_s *rsp_fchs)
3730 {
3731 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3732 	struct bfa_fcs_lport_s *port = ns->port;
3733 	struct ct_hdr_s *cthdr = NULL;
3734 
3735 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3736 
3737 	/*
3738 	 * Sanity Checks
3739 	 */
3740 	if (req_status != BFA_STATUS_OK) {
3741 		bfa_trc(port->fcs, req_status);
3742 		port->stats.ns_rspnid_rsp_err++;
3743 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3744 		return;
3745 	}
3746 
3747 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3748 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3749 
3750 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3751 		port->stats.ns_rspnid_accepts++;
3752 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3753 		return;
3754 	}
3755 
3756 	port->stats.ns_rspnid_rejects++;
3757 	bfa_trc(port->fcs, cthdr->reason_code);
3758 	bfa_trc(port->fcs, cthdr->exp_code);
3759 	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3760 }
3761 
3762 /*
3763  * Register FC4-Types
3764  */
3765 static void
bfa_fcs_lport_ns_send_rft_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3766 bfa_fcs_lport_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3767 {
3768 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3769 	struct bfa_fcs_lport_s *port = ns->port;
3770 	struct fchs_s fchs;
3771 	int             len;
3772 	struct bfa_fcxp_s *fcxp;
3773 
3774 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3775 
3776 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3777 	if (!fcxp) {
3778 		port->stats.ns_rftid_alloc_wait++;
3779 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3780 					bfa_fcs_lport_ns_send_rft_id, ns);
3781 		return;
3782 	}
3783 	ns->fcxp = fcxp;
3784 
3785 	len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3786 		     bfa_fcs_lport_get_fcid(port), 0, port->port_cfg.roles);
3787 
3788 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3789 			  FC_CLASS_3, len, &fchs,
3790 			  bfa_fcs_lport_ns_rft_id_response, (void *)ns,
3791 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3792 
3793 	port->stats.ns_rftid_sent++;
3794 	bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT);
3795 }
3796 
3797 static void
bfa_fcs_lport_ns_rft_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3798 bfa_fcs_lport_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3799 				void *cbarg, bfa_status_t req_status,
3800 				u32 rsp_len, u32 resid_len,
3801 				struct fchs_s *rsp_fchs)
3802 {
3803 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3804 	struct bfa_fcs_lport_s *port = ns->port;
3805 	struct ct_hdr_s *cthdr = NULL;
3806 
3807 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3808 
3809 	/*
3810 	 * Sanity Checks
3811 	 */
3812 	if (req_status != BFA_STATUS_OK) {
3813 		bfa_trc(port->fcs, req_status);
3814 		port->stats.ns_rftid_rsp_err++;
3815 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3816 		return;
3817 	}
3818 
3819 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3820 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3821 
3822 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3823 		port->stats.ns_rftid_accepts++;
3824 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3825 		return;
3826 	}
3827 
3828 	port->stats.ns_rftid_rejects++;
3829 	bfa_trc(port->fcs, cthdr->reason_code);
3830 	bfa_trc(port->fcs, cthdr->exp_code);
3831 	bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3832 }
3833 
3834 /*
3835  * Register FC4-Features : Should be done after RFT_ID
3836  */
3837 static void
bfa_fcs_lport_ns_send_rff_id(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3838 bfa_fcs_lport_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3839 {
3840 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3841 	struct bfa_fcs_lport_s *port = ns->port;
3842 	struct fchs_s fchs;
3843 	int             len;
3844 	struct bfa_fcxp_s *fcxp;
3845 	u8			fc4_ftrs = 0;
3846 
3847 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3848 
3849 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3850 	if (!fcxp) {
3851 		port->stats.ns_rffid_alloc_wait++;
3852 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3853 					bfa_fcs_lport_ns_send_rff_id, ns);
3854 		return;
3855 	}
3856 	ns->fcxp = fcxp;
3857 
3858 	if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port))
3859 		fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR;
3860 
3861 	len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3862 			     bfa_fcs_lport_get_fcid(port), 0,
3863 				 FC_TYPE_FCP, fc4_ftrs);
3864 
3865 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3866 			  FC_CLASS_3, len, &fchs,
3867 			  bfa_fcs_lport_ns_rff_id_response, (void *)ns,
3868 			  FC_MAX_PDUSZ, FC_FCCT_TOV);
3869 
3870 	port->stats.ns_rffid_sent++;
3871 	bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT);
3872 }
3873 
3874 static void
bfa_fcs_lport_ns_rff_id_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3875 bfa_fcs_lport_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3876 				void *cbarg, bfa_status_t req_status,
3877 				u32 rsp_len, u32 resid_len,
3878 				struct fchs_s *rsp_fchs)
3879 {
3880 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3881 	struct bfa_fcs_lport_s *port = ns->port;
3882 	struct ct_hdr_s *cthdr = NULL;
3883 
3884 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3885 
3886 	/*
3887 	 * Sanity Checks
3888 	 */
3889 	if (req_status != BFA_STATUS_OK) {
3890 		bfa_trc(port->fcs, req_status);
3891 		port->stats.ns_rffid_rsp_err++;
3892 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3893 		return;
3894 	}
3895 
3896 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3897 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3898 
3899 	if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
3900 		port->stats.ns_rffid_accepts++;
3901 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3902 		return;
3903 	}
3904 
3905 	port->stats.ns_rffid_rejects++;
3906 	bfa_trc(port->fcs, cthdr->reason_code);
3907 	bfa_trc(port->fcs, cthdr->exp_code);
3908 
3909 	if (cthdr->reason_code == CT_RSN_NOT_SUPP) {
3910 		/* if this command is not supported, we don't retry */
3911 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
3912 	} else
3913 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3914 }
3915 /*
3916  * Query Fabric for FC4-Types Devices.
3917  *
3918 * TBD : Need to use a local (FCS private) response buffer, since the response
3919  * can be larger than 2K.
3920  */
3921 static void
bfa_fcs_lport_ns_send_gid_ft(void * ns_cbarg,struct bfa_fcxp_s * fcxp_alloced)3922 bfa_fcs_lport_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
3923 {
3924 	struct bfa_fcs_lport_ns_s *ns = ns_cbarg;
3925 	struct bfa_fcs_lport_s *port = ns->port;
3926 	struct fchs_s fchs;
3927 	int             len;
3928 	struct bfa_fcxp_s *fcxp;
3929 
3930 	bfa_trc(port->fcs, port->pid);
3931 
3932 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
3933 	if (!fcxp) {
3934 		port->stats.ns_gidft_alloc_wait++;
3935 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe,
3936 					bfa_fcs_lport_ns_send_gid_ft, ns);
3937 		return;
3938 	}
3939 	ns->fcxp = fcxp;
3940 
3941 	/*
3942 	 * This query is only initiated for FCP initiator mode.
3943 	 */
3944 	len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
3945 			      ns->port->pid, FC_TYPE_FCP);
3946 
3947 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
3948 			  FC_CLASS_3, len, &fchs,
3949 			  bfa_fcs_lport_ns_gid_ft_response, (void *)ns,
3950 			  bfa_fcxp_get_maxrsp(port->fcs->bfa), FC_FCCT_TOV);
3951 
3952 	port->stats.ns_gidft_sent++;
3953 
3954 	bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT);
3955 }
3956 
3957 static void
bfa_fcs_lport_ns_gid_ft_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)3958 bfa_fcs_lport_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
3959 				void *cbarg, bfa_status_t req_status,
3960 				u32 rsp_len, u32 resid_len,
3961 				struct fchs_s *rsp_fchs)
3962 {
3963 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) cbarg;
3964 	struct bfa_fcs_lport_s *port = ns->port;
3965 	struct ct_hdr_s *cthdr = NULL;
3966 	u32        n_pids;
3967 
3968 	bfa_trc(port->fcs, port->port_cfg.pwwn);
3969 
3970 	/*
3971 	 * Sanity Checks
3972 	 */
3973 	if (req_status != BFA_STATUS_OK) {
3974 		bfa_trc(port->fcs, req_status);
3975 		port->stats.ns_gidft_rsp_err++;
3976 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
3977 		return;
3978 	}
3979 
3980 	if (resid_len != 0) {
3981 		/*
3982 		 * TBD : we will need to allocate a larger buffer & retry the
3983 		 * command
3984 		 */
3985 		bfa_trc(port->fcs, rsp_len);
3986 		bfa_trc(port->fcs, resid_len);
3987 		return;
3988 	}
3989 
3990 	cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
3991 	cthdr->cmd_rsp_code = be16_to_cpu(cthdr->cmd_rsp_code);
3992 
3993 	switch (cthdr->cmd_rsp_code) {
3994 
3995 	case CT_RSP_ACCEPT:
3996 
3997 		port->stats.ns_gidft_accepts++;
3998 		n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32));
3999 		bfa_trc(port->fcs, n_pids);
4000 		bfa_fcs_lport_ns_process_gidft_pids(port,
4001 						   (u32 *) (cthdr + 1),
4002 						   n_pids);
4003 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4004 		break;
4005 
4006 	case CT_RSP_REJECT:
4007 
4008 		/*
4009 		 * Check the reason code  & explanation.
4010 		 * There may not have been any FC4 devices in the fabric
4011 		 */
4012 		port->stats.ns_gidft_rejects++;
4013 		bfa_trc(port->fcs, cthdr->reason_code);
4014 		bfa_trc(port->fcs, cthdr->exp_code);
4015 
4016 		if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF)
4017 		    && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) {
4018 
4019 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK);
4020 		} else {
4021 			/*
4022 			 * for all other errors, retry
4023 			 */
4024 			bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4025 		}
4026 		break;
4027 
4028 	default:
4029 		port->stats.ns_gidft_unknown_rsp++;
4030 		bfa_trc(port->fcs, cthdr->cmd_rsp_code);
4031 		bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR);
4032 	}
4033 }
4034 
4035 /*
4036  *     This routine will be called by bfa_timer on timer timeouts.
4037  *
4038  *	param[in]	port - pointer to bfa_fcs_lport_t.
4039  *
4040  *	return
4041  *		void
4042  *
4043  *	Special Considerations:
4044  *
4045  *	note
4046  */
4047 static void
bfa_fcs_lport_ns_timeout(void * arg)4048 bfa_fcs_lport_ns_timeout(void *arg)
4049 {
4050 	struct bfa_fcs_lport_ns_s *ns = (struct bfa_fcs_lport_ns_s *) arg;
4051 
4052 	ns->port->stats.ns_timeouts++;
4053 	bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT);
4054 }
4055 
4056 /*
4057  * Process the PID list in GID_FT response
4058  */
4059 static void
bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s * port,u32 * pid_buf,u32 n_pids)4060 bfa_fcs_lport_ns_process_gidft_pids(struct bfa_fcs_lport_s *port, u32 *pid_buf,
4061 				   u32 n_pids)
4062 {
4063 	struct fcgs_gidft_resp_s *gidft_entry;
4064 	struct bfa_fcs_rport_s *rport;
4065 	u32        ii;
4066 
4067 	for (ii = 0; ii < n_pids; ii++) {
4068 		gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii];
4069 
4070 		if (gidft_entry->pid == port->pid)
4071 			continue;
4072 
4073 		/*
4074 		 * Check if this rport already exists
4075 		 */
4076 		rport = bfa_fcs_lport_get_rport_by_pid(port, gidft_entry->pid);
4077 		if (rport == NULL) {
4078 			/*
4079 			 * this is a new device. create rport
4080 			 */
4081 			rport = bfa_fcs_rport_create(port, gidft_entry->pid);
4082 		} else {
4083 			/*
4084 			 * this rport already exists
4085 			 */
4086 			bfa_fcs_rport_scn(rport);
4087 		}
4088 
4089 		bfa_trc(port->fcs, gidft_entry->pid);
4090 
4091 		/*
4092 		 * if the last entry bit is set, bail out.
4093 		 */
4094 		if (gidft_entry->last)
4095 			return;
4096 	}
4097 }
4098 
4099 /*
4100  *  fcs_ns_public FCS nameserver public interfaces
4101  */
4102 
4103 /*
4104  * Functions called by port/fab.
4105  * These will send relevant Events to the ns state machine.
4106  */
4107 void
bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s * port)4108 bfa_fcs_lport_ns_init(struct bfa_fcs_lport_s *port)
4109 {
4110 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4111 
4112 	ns->port = port;
4113 	bfa_sm_set_state(ns, bfa_fcs_lport_ns_sm_offline);
4114 }
4115 
4116 void
bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s * port)4117 bfa_fcs_lport_ns_offline(struct bfa_fcs_lport_s *port)
4118 {
4119 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4120 
4121 	ns->port = port;
4122 	bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE);
4123 }
4124 
4125 void
bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s * port)4126 bfa_fcs_lport_ns_online(struct bfa_fcs_lport_s *port)
4127 {
4128 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4129 
4130 	ns->port = port;
4131 	bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE);
4132 }
4133 
4134 void
bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s * port)4135 bfa_fcs_lport_ns_query(struct bfa_fcs_lport_s *port)
4136 {
4137 	struct bfa_fcs_lport_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port);
4138 
4139 	bfa_trc(port->fcs, port->pid);
4140 	bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY);
4141 }
4142 
4143 static void
bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t * port)4144 bfa_fcs_lport_ns_boot_target_disc(bfa_fcs_lport_t *port)
4145 {
4146 
4147 	struct bfa_fcs_rport_s *rport;
4148 	u8 nwwns;
4149 	wwn_t  wwns[BFA_PREBOOT_BOOTLUN_MAX];
4150 	int ii;
4151 
4152 	bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, wwns);
4153 
4154 	for (ii = 0 ; ii < nwwns; ++ii) {
4155 		rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]);
4156 		WARN_ON(!rport);
4157 	}
4158 }
4159 
4160 /*
4161  * FCS SCN
4162  */
4163 
4164 #define FC_QOS_RSCN_EVENT		0x0c
4165 #define FC_FABRIC_NAME_RSCN_EVENT	0x0d
4166 
4167 /*
4168  * forward declarations
4169  */
4170 static void     bfa_fcs_lport_scn_send_scr(void *scn_cbarg,
4171 					  struct bfa_fcxp_s *fcxp_alloced);
4172 static void     bfa_fcs_lport_scn_scr_response(void *fcsarg,
4173 					      struct bfa_fcxp_s *fcxp,
4174 					      void *cbarg,
4175 					      bfa_status_t req_status,
4176 					      u32 rsp_len,
4177 					      u32 resid_len,
4178 					      struct fchs_s *rsp_fchs);
4179 static void     bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4180 					     struct fchs_s *rx_fchs);
4181 static void     bfa_fcs_lport_scn_timeout(void *arg);
4182 
4183 /*
4184  *  fcs_scm_sm FCS SCN state machine
4185  */
4186 
4187 /*
4188  * VPort SCN State Machine events
4189  */
4190 enum port_scn_event {
4191 	SCNSM_EVENT_PORT_ONLINE = 1,
4192 	SCNSM_EVENT_PORT_OFFLINE = 2,
4193 	SCNSM_EVENT_RSP_OK = 3,
4194 	SCNSM_EVENT_RSP_ERROR = 4,
4195 	SCNSM_EVENT_TIMEOUT = 5,
4196 	SCNSM_EVENT_SCR_SENT = 6,
4197 };
4198 
4199 static void     bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4200 					    enum port_scn_event event);
4201 static void     bfa_fcs_lport_scn_sm_sending_scr(
4202 					struct bfa_fcs_lport_scn_s *scn,
4203 					enum port_scn_event event);
4204 static void     bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4205 					enum port_scn_event event);
4206 static void     bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4207 					      enum port_scn_event event);
4208 static void     bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4209 					   enum port_scn_event event);
4210 
4211 /*
4212  *	Starting state - awaiting link up.
4213  */
4214 static void
bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4215 bfa_fcs_lport_scn_sm_offline(struct bfa_fcs_lport_scn_s *scn,
4216 			enum port_scn_event event)
4217 {
4218 	switch (event) {
4219 	case SCNSM_EVENT_PORT_ONLINE:
4220 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4221 		bfa_fcs_lport_scn_send_scr(scn, NULL);
4222 		break;
4223 
4224 	case SCNSM_EVENT_PORT_OFFLINE:
4225 		break;
4226 
4227 	default:
4228 		bfa_sm_fault(scn->port->fcs, event);
4229 	}
4230 }
4231 
4232 static void
bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4233 bfa_fcs_lport_scn_sm_sending_scr(struct bfa_fcs_lport_scn_s *scn,
4234 				enum port_scn_event event)
4235 {
4236 	switch (event) {
4237 	case SCNSM_EVENT_SCR_SENT:
4238 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr);
4239 		break;
4240 
4241 	case SCNSM_EVENT_PORT_OFFLINE:
4242 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4243 		bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe);
4244 		break;
4245 
4246 	default:
4247 		bfa_sm_fault(scn->port->fcs, event);
4248 	}
4249 }
4250 
4251 static void
bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4252 bfa_fcs_lport_scn_sm_scr(struct bfa_fcs_lport_scn_s *scn,
4253 			enum port_scn_event event)
4254 {
4255 	struct bfa_fcs_lport_s *port = scn->port;
4256 
4257 	switch (event) {
4258 	case SCNSM_EVENT_RSP_OK:
4259 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_online);
4260 		break;
4261 
4262 	case SCNSM_EVENT_RSP_ERROR:
4263 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_scr_retry);
4264 		bfa_timer_start(port->fcs->bfa, &scn->timer,
4265 				    bfa_fcs_lport_scn_timeout, scn,
4266 				    BFA_FCS_RETRY_TIMEOUT);
4267 		break;
4268 
4269 	case SCNSM_EVENT_PORT_OFFLINE:
4270 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4271 		bfa_fcxp_discard(scn->fcxp);
4272 		break;
4273 
4274 	default:
4275 		bfa_sm_fault(port->fcs, event);
4276 	}
4277 }
4278 
4279 static void
bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4280 bfa_fcs_lport_scn_sm_scr_retry(struct bfa_fcs_lport_scn_s *scn,
4281 				enum port_scn_event event)
4282 {
4283 	switch (event) {
4284 	case SCNSM_EVENT_TIMEOUT:
4285 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_sending_scr);
4286 		bfa_fcs_lport_scn_send_scr(scn, NULL);
4287 		break;
4288 
4289 	case SCNSM_EVENT_PORT_OFFLINE:
4290 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4291 		bfa_timer_stop(&scn->timer);
4292 		break;
4293 
4294 	default:
4295 		bfa_sm_fault(scn->port->fcs, event);
4296 	}
4297 }
4298 
4299 static void
bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s * scn,enum port_scn_event event)4300 bfa_fcs_lport_scn_sm_online(struct bfa_fcs_lport_scn_s *scn,
4301 			enum port_scn_event event)
4302 {
4303 	switch (event) {
4304 	case SCNSM_EVENT_PORT_OFFLINE:
4305 		bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4306 		break;
4307 
4308 	default:
4309 		bfa_sm_fault(scn->port->fcs, event);
4310 	}
4311 }
4312 
4313 
4314 
4315 /*
4316  *  fcs_scn_private FCS SCN private functions
4317  */
4318 
4319 /*
4320  * This routine will be called to send a SCR command.
4321  */
4322 static void
bfa_fcs_lport_scn_send_scr(void * scn_cbarg,struct bfa_fcxp_s * fcxp_alloced)4323 bfa_fcs_lport_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced)
4324 {
4325 	struct bfa_fcs_lport_scn_s *scn = scn_cbarg;
4326 	struct bfa_fcs_lport_s *port = scn->port;
4327 	struct fchs_s fchs;
4328 	int             len;
4329 	struct bfa_fcxp_s *fcxp;
4330 
4331 	bfa_trc(port->fcs, port->pid);
4332 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4333 
4334 	fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
4335 	if (!fcxp) {
4336 		bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe,
4337 					bfa_fcs_lport_scn_send_scr, scn);
4338 		return;
4339 	}
4340 	scn->fcxp = fcxp;
4341 
4342 	/* Handle VU registrations for Base port only */
4343 	if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) {
4344 		len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4345 				port->fabric->lps->brcd_switch,
4346 				port->pid, 0);
4347 	} else {
4348 	    len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4349 				    BFA_FALSE,
4350 				    port->pid, 0);
4351 	}
4352 
4353 	bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
4354 			  FC_CLASS_3, len, &fchs,
4355 			  bfa_fcs_lport_scn_scr_response,
4356 			  (void *)scn, FC_MAX_PDUSZ, FC_ELS_TOV);
4357 
4358 	bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT);
4359 }
4360 
4361 static void
bfa_fcs_lport_scn_scr_response(void * fcsarg,struct bfa_fcxp_s * fcxp,void * cbarg,bfa_status_t req_status,u32 rsp_len,u32 resid_len,struct fchs_s * rsp_fchs)4362 bfa_fcs_lport_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp,
4363 			void *cbarg, bfa_status_t req_status, u32 rsp_len,
4364 			      u32 resid_len, struct fchs_s *rsp_fchs)
4365 {
4366 	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) cbarg;
4367 	struct bfa_fcs_lport_s *port = scn->port;
4368 	struct fc_els_cmd_s *els_cmd;
4369 	struct fc_ls_rjt_s *ls_rjt;
4370 
4371 	bfa_trc(port->fcs, port->port_cfg.pwwn);
4372 
4373 	/*
4374 	 * Sanity Checks
4375 	 */
4376 	if (req_status != BFA_STATUS_OK) {
4377 		bfa_trc(port->fcs, req_status);
4378 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4379 		return;
4380 	}
4381 
4382 	els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
4383 
4384 	switch (els_cmd->els_code) {
4385 
4386 	case FC_ELS_ACC:
4387 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK);
4388 		break;
4389 
4390 	case FC_ELS_LS_RJT:
4391 
4392 		ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
4393 
4394 		bfa_trc(port->fcs, ls_rjt->reason_code);
4395 		bfa_trc(port->fcs, ls_rjt->reason_code_expl);
4396 
4397 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4398 		break;
4399 
4400 	default:
4401 		bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR);
4402 	}
4403 }
4404 
4405 /*
4406  * Send a LS Accept
4407  */
4408 static void
bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s * port,struct fchs_s * rx_fchs)4409 bfa_fcs_lport_scn_send_ls_acc(struct bfa_fcs_lport_s *port,
4410 				struct fchs_s *rx_fchs)
4411 {
4412 	struct fchs_s fchs;
4413 	struct bfa_fcxp_s *fcxp;
4414 	struct bfa_rport_s *bfa_rport = NULL;
4415 	int             len;
4416 
4417 	bfa_trc(port->fcs, rx_fchs->s_id);
4418 
4419 	fcxp = bfa_fcs_fcxp_alloc(port->fcs);
4420 	if (!fcxp)
4421 		return;
4422 
4423 	len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
4424 			      rx_fchs->s_id, bfa_fcs_lport_get_fcid(port),
4425 			      rx_fchs->ox_id);
4426 
4427 	bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag,
4428 			  BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
4429 			  FC_MAX_PDUSZ, 0);
4430 }
4431 
4432 /*
4433  *     This routine will be called by bfa_timer on timer timeouts.
4434  *
4435  *	param[in]	vport		- pointer to bfa_fcs_lport_t.
4436  *	param[out]	vport_status	- pointer to return vport status in
4437  *
4438  *	return
4439  *		void
4440  *
4441  *	Special Considerations:
4442  *
4443  *	note
4444  */
4445 static void
bfa_fcs_lport_scn_timeout(void * arg)4446 bfa_fcs_lport_scn_timeout(void *arg)
4447 {
4448 	struct bfa_fcs_lport_scn_s *scn = (struct bfa_fcs_lport_scn_s *) arg;
4449 
4450 	bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT);
4451 }
4452 
4453 
4454 
4455 /*
4456  *  fcs_scn_public FCS state change notification public interfaces
4457  */
4458 
4459 /*
4460  * Functions called by port/fab
4461  */
4462 void
bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s * port)4463 bfa_fcs_lport_scn_init(struct bfa_fcs_lport_s *port)
4464 {
4465 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4466 
4467 	scn->port = port;
4468 	bfa_sm_set_state(scn, bfa_fcs_lport_scn_sm_offline);
4469 }
4470 
4471 void
bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s * port)4472 bfa_fcs_lport_scn_offline(struct bfa_fcs_lport_s *port)
4473 {
4474 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4475 
4476 	scn->port = port;
4477 	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE);
4478 }
4479 
4480 void
bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s * port)4481 bfa_fcs_lport_scn_online(struct bfa_fcs_lport_s *port)
4482 {
4483 	struct bfa_fcs_lport_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port);
4484 
4485 	scn->port = port;
4486 	bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE);
4487 }
4488 
4489 static void
bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s * port,u32 rpid)4490 bfa_fcs_lport_scn_portid_rscn(struct bfa_fcs_lport_s *port, u32 rpid)
4491 {
4492 	struct bfa_fcs_rport_s *rport;
4493 
4494 	bfa_trc(port->fcs, rpid);
4495 
4496 	/*
4497 	 * If this is an unknown device, then it just came online.
4498 	 * Otherwise let rport handle the RSCN event.
4499 	 */
4500 	rport = bfa_fcs_lport_get_rport_by_pid(port, rpid);
4501 	if (rport == NULL) {
4502 		/*
4503 		 * If min cfg mode is enabled, we donot need to
4504 		 * discover any new rports.
4505 		 */
4506 		if (!__fcs_min_cfg(port->fcs))
4507 			rport = bfa_fcs_rport_create(port, rpid);
4508 	} else
4509 		bfa_fcs_rport_scn(rport);
4510 }
4511 
4512 /*
4513  * rscn format based PID comparison
4514  */
4515 #define __fc_pid_match(__c0, __c1, __fmt)		\
4516 	(((__fmt) == FC_RSCN_FORMAT_FABRIC) ||		\
4517 	 (((__fmt) == FC_RSCN_FORMAT_DOMAIN) &&		\
4518 	  ((__c0)[0] == (__c1)[0])) ||				\
4519 	 (((__fmt) == FC_RSCN_FORMAT_AREA) &&		\
4520 	  ((__c0)[0] == (__c1)[0]) &&				\
4521 	  ((__c0)[1] == (__c1)[1])))
4522 
4523 static void
bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s * port,enum fc_rscn_format format,u32 rscn_pid)4524 bfa_fcs_lport_scn_multiport_rscn(struct bfa_fcs_lport_s *port,
4525 				enum fc_rscn_format format,
4526 				u32 rscn_pid)
4527 {
4528 	struct bfa_fcs_rport_s *rport;
4529 	struct list_head        *qe, *qe_next;
4530 	u8        *c0, *c1;
4531 
4532 	bfa_trc(port->fcs, format);
4533 	bfa_trc(port->fcs, rscn_pid);
4534 
4535 	c0 = (u8 *) &rscn_pid;
4536 
4537 	list_for_each_safe(qe, qe_next, &port->rport_q) {
4538 		rport = (struct bfa_fcs_rport_s *) qe;
4539 		c1 = (u8 *) &rport->pid;
4540 		if (__fc_pid_match(c0, c1, format))
4541 			bfa_fcs_rport_scn(rport);
4542 	}
4543 }
4544 
4545 
4546 void
bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s * port,struct fchs_s * fchs,u32 len)4547 bfa_fcs_lport_scn_process_rscn(struct bfa_fcs_lport_s *port,
4548 			struct fchs_s *fchs, u32 len)
4549 {
4550 	struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1);
4551 	int             num_entries;
4552 	u32        rscn_pid;
4553 	bfa_boolean_t   nsquery = BFA_FALSE, found;
4554 	int             i = 0, j;
4555 
4556 	num_entries =
4557 		(be16_to_cpu(rscn->payldlen) -
4558 		 sizeof(u32)) / sizeof(rscn->event[0]);
4559 
4560 	bfa_trc(port->fcs, num_entries);
4561 
4562 	port->stats.num_rscn++;
4563 
4564 	bfa_fcs_lport_scn_send_ls_acc(port, fchs);
4565 
4566 	for (i = 0; i < num_entries; i++) {
4567 		rscn_pid = rscn->event[i].portid;
4568 
4569 		bfa_trc(port->fcs, rscn->event[i].format);
4570 		bfa_trc(port->fcs, rscn_pid);
4571 
4572 		/* check for duplicate entries in the list */
4573 		found = BFA_FALSE;
4574 		for (j = 0; j < i; j++) {
4575 			if (rscn->event[j].portid == rscn_pid) {
4576 				found = BFA_TRUE;
4577 				break;
4578 			}
4579 		}
4580 
4581 		/* if found in down the list, pid has been already processed */
4582 		if (found) {
4583 			bfa_trc(port->fcs, rscn_pid);
4584 			continue;
4585 		}
4586 
4587 		switch (rscn->event[i].format) {
4588 		case FC_RSCN_FORMAT_PORTID:
4589 			if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) {
4590 				/*
4591 				 * Ignore this event.
4592 				 * f/w would have processed it
4593 				 */
4594 				bfa_trc(port->fcs, rscn_pid);
4595 			} else {
4596 				port->stats.num_portid_rscn++;
4597 				bfa_fcs_lport_scn_portid_rscn(port, rscn_pid);
4598 			}
4599 		break;
4600 
4601 		case FC_RSCN_FORMAT_FABRIC:
4602 			if (rscn->event[i].qualifier ==
4603 					FC_FABRIC_NAME_RSCN_EVENT) {
4604 				bfa_fcs_lport_ms_fabric_rscn(port);
4605 				break;
4606 			}
4607 			/* !!!!!!!!! Fall Through !!!!!!!!!!!!! */
4608 
4609 		case FC_RSCN_FORMAT_AREA:
4610 		case FC_RSCN_FORMAT_DOMAIN:
4611 			nsquery = BFA_TRUE;
4612 			bfa_fcs_lport_scn_multiport_rscn(port,
4613 							rscn->event[i].format,
4614 							rscn_pid);
4615 			break;
4616 
4617 
4618 		default:
4619 			WARN_ON(1);
4620 			nsquery = BFA_TRUE;
4621 		}
4622 	}
4623 
4624 	/*
4625 	 * If any of area, domain or fabric RSCN is received, do a fresh
4626 	 * discovery to find new devices.
4627 	 */
4628 	if (nsquery)
4629 		bfa_fcs_lport_ns_query(port);
4630 }
4631 
4632 /*
4633  * BFA FCS port
4634  */
4635 /*
4636  *  fcs_port_api BFA FCS port API
4637  */
4638 struct bfa_fcs_lport_s *
bfa_fcs_get_base_port(struct bfa_fcs_s * fcs)4639 bfa_fcs_get_base_port(struct bfa_fcs_s *fcs)
4640 {
4641 	return &fcs->fabric.bport;
4642 }
4643 
4644 wwn_t
bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s * port,wwn_t wwn,int index,int nrports,bfa_boolean_t bwwn)4645 bfa_fcs_lport_get_rport(struct bfa_fcs_lport_s *port, wwn_t wwn, int index,
4646 		int nrports, bfa_boolean_t bwwn)
4647 {
4648 	struct list_head	*qh, *qe;
4649 	struct bfa_fcs_rport_s *rport = NULL;
4650 	int	i;
4651 	struct bfa_fcs_s	*fcs;
4652 
4653 	if (port == NULL || nrports == 0)
4654 		return (wwn_t) 0;
4655 
4656 	fcs = port->fcs;
4657 	bfa_trc(fcs, (u32) nrports);
4658 
4659 	i = 0;
4660 	qh = &port->rport_q;
4661 	qe = bfa_q_first(qh);
4662 
4663 	while ((qe != qh) && (i < nrports)) {
4664 		rport = (struct bfa_fcs_rport_s *) qe;
4665 		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4666 			qe = bfa_q_next(qe);
4667 			bfa_trc(fcs, (u32) rport->pwwn);
4668 			bfa_trc(fcs, rport->pid);
4669 			bfa_trc(fcs, i);
4670 			continue;
4671 		}
4672 
4673 		if (bwwn) {
4674 			if (!memcmp(&wwn, &rport->pwwn, 8))
4675 				break;
4676 		} else {
4677 			if (i == index)
4678 				break;
4679 		}
4680 
4681 		i++;
4682 		qe = bfa_q_next(qe);
4683 	}
4684 
4685 	bfa_trc(fcs, i);
4686 	if (rport)
4687 		return rport->pwwn;
4688 	else
4689 		return (wwn_t) 0;
4690 }
4691 
4692 void
bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s * port,wwn_t rport_wwns[],int * nrports)4693 bfa_fcs_lport_get_rports(struct bfa_fcs_lport_s *port,
4694 	 wwn_t rport_wwns[], int *nrports)
4695 {
4696 	struct list_head	*qh, *qe;
4697 	struct bfa_fcs_rport_s *rport = NULL;
4698 	int	i;
4699 	struct bfa_fcs_s	*fcs;
4700 
4701 	if (port == NULL || rport_wwns == NULL || *nrports == 0)
4702 		return;
4703 
4704 	fcs = port->fcs;
4705 	bfa_trc(fcs, (u32) *nrports);
4706 
4707 	i = 0;
4708 	qh = &port->rport_q;
4709 	qe = bfa_q_first(qh);
4710 
4711 	while ((qe != qh) && (i < *nrports)) {
4712 		rport = (struct bfa_fcs_rport_s *) qe;
4713 		if (bfa_ntoh3b(rport->pid) > 0xFFF000) {
4714 			qe = bfa_q_next(qe);
4715 			bfa_trc(fcs, (u32) rport->pwwn);
4716 			bfa_trc(fcs, rport->pid);
4717 			bfa_trc(fcs, i);
4718 			continue;
4719 		}
4720 
4721 		rport_wwns[i] = rport->pwwn;
4722 
4723 		i++;
4724 		qe = bfa_q_next(qe);
4725 	}
4726 
4727 	bfa_trc(fcs, i);
4728 	*nrports = i;
4729 }
4730 
4731 /*
4732  * Iterate's through all the rport's in the given port to
4733  * determine the maximum operating speed.
4734  *
4735  * !!!! To be used in TRL Functionality only !!!!
4736  */
4737 bfa_port_speed_t
bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t * port)4738 bfa_fcs_lport_get_rport_max_speed(bfa_fcs_lport_t *port)
4739 {
4740 	struct list_head *qh, *qe;
4741 	struct bfa_fcs_rport_s *rport = NULL;
4742 	struct bfa_fcs_s	*fcs;
4743 	bfa_port_speed_t max_speed = 0;
4744 	struct bfa_port_attr_s port_attr;
4745 	bfa_port_speed_t port_speed, rport_speed;
4746 	bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa);
4747 
4748 
4749 	if (port == NULL)
4750 		return 0;
4751 
4752 	fcs = port->fcs;
4753 
4754 	/* Get Physical port's current speed */
4755 	bfa_fcport_get_attr(port->fcs->bfa, &port_attr);
4756 	port_speed = port_attr.speed;
4757 	bfa_trc(fcs, port_speed);
4758 
4759 	qh = &port->rport_q;
4760 	qe = bfa_q_first(qh);
4761 
4762 	while (qe != qh) {
4763 		rport = (struct bfa_fcs_rport_s *) qe;
4764 		if ((bfa_ntoh3b(rport->pid) > 0xFFF000) ||
4765 			(bfa_fcs_rport_get_state(rport) ==
4766 			  BFA_RPORT_OFFLINE)) {
4767 			qe = bfa_q_next(qe);
4768 			continue;
4769 		}
4770 
4771 		rport_speed = rport->rpf.rpsc_speed;
4772 		if ((trl_enabled) && (rport_speed ==
4773 			BFA_PORT_SPEED_UNKNOWN)) {
4774 			/* Use default ratelim speed setting */
4775 			rport_speed =
4776 				bfa_fcport_get_ratelim_speed(port->fcs->bfa);
4777 		}
4778 
4779 		if	((rport_speed  == BFA_PORT_SPEED_8GBPS) ||
4780 			(rport_speed > port_speed)) {
4781 			max_speed = rport_speed;
4782 			break;
4783 		} else if (rport_speed > max_speed) {
4784 			max_speed = rport_speed;
4785 		}
4786 
4787 		qe = bfa_q_next(qe);
4788 	}
4789 
4790 	bfa_trc(fcs, max_speed);
4791 	return max_speed;
4792 }
4793 
4794 struct bfa_fcs_lport_s *
bfa_fcs_lookup_port(struct bfa_fcs_s * fcs,u16 vf_id,wwn_t lpwwn)4795 bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn)
4796 {
4797 	struct bfa_fcs_vport_s *vport;
4798 	bfa_fcs_vf_t   *vf;
4799 
4800 	WARN_ON(fcs == NULL);
4801 
4802 	vf = bfa_fcs_vf_lookup(fcs, vf_id);
4803 	if (vf == NULL) {
4804 		bfa_trc(fcs, vf_id);
4805 		return NULL;
4806 	}
4807 
4808 	if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn))
4809 		return &vf->bport;
4810 
4811 	vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn);
4812 	if (vport)
4813 		return &vport->lport;
4814 
4815 	return NULL;
4816 }
4817 
4818 /*
4819  *  API corresponding to NPIV_VPORT_GETINFO.
4820  */
4821 void
bfa_fcs_lport_get_info(struct bfa_fcs_lport_s * port,struct bfa_lport_info_s * port_info)4822 bfa_fcs_lport_get_info(struct bfa_fcs_lport_s *port,
4823 	 struct bfa_lport_info_s *port_info)
4824 {
4825 
4826 	bfa_trc(port->fcs, port->fabric->fabric_name);
4827 
4828 	if (port->vport == NULL) {
4829 		/*
4830 		 * This is a Physical port
4831 		 */
4832 		port_info->port_type = BFA_LPORT_TYPE_PHYSICAL;
4833 
4834 		/*
4835 		 * @todo : need to fix the state & reason
4836 		 */
4837 		port_info->port_state = 0;
4838 		port_info->offline_reason = 0;
4839 
4840 		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4841 		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4842 
4843 		port_info->max_vports_supp =
4844 			bfa_lps_get_max_vport(port->fcs->bfa);
4845 		port_info->num_vports_inuse =
4846 			port->fabric->num_vports;
4847 		port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP;
4848 		port_info->num_rports_inuse = port->num_rports;
4849 	} else {
4850 		/*
4851 		 * This is a virtual port
4852 		 */
4853 		port_info->port_type = BFA_LPORT_TYPE_VIRTUAL;
4854 
4855 		/*
4856 		 * @todo : need to fix the state & reason
4857 		 */
4858 		port_info->port_state = 0;
4859 		port_info->offline_reason = 0;
4860 
4861 		port_info->port_wwn = bfa_fcs_lport_get_pwwn(port);
4862 		port_info->node_wwn = bfa_fcs_lport_get_nwwn(port);
4863 	}
4864 }
4865 
4866 void
bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s * fcs_port,struct bfa_lport_stats_s * port_stats)4867 bfa_fcs_lport_get_stats(struct bfa_fcs_lport_s *fcs_port,
4868 	 struct bfa_lport_stats_s *port_stats)
4869 {
4870 	*port_stats = fcs_port->stats;
4871 }
4872 
4873 void
bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s * fcs_port)4874 bfa_fcs_lport_clear_stats(struct bfa_fcs_lport_s *fcs_port)
4875 {
4876 	memset(&fcs_port->stats, 0, sizeof(struct bfa_lport_stats_s));
4877 }
4878 
4879 /*
4880  * FCS virtual port state machine
4881  */
4882 
4883 #define __vport_fcs(__vp)       ((__vp)->lport.fcs)
4884 #define __vport_pwwn(__vp)      ((__vp)->lport.port_cfg.pwwn)
4885 #define __vport_nwwn(__vp)      ((__vp)->lport.port_cfg.nwwn)
4886 #define __vport_bfa(__vp)       ((__vp)->lport.fcs->bfa)
4887 #define __vport_fcid(__vp)      ((__vp)->lport.pid)
4888 #define __vport_fabric(__vp)    ((__vp)->lport.fabric)
4889 #define __vport_vfid(__vp)      ((__vp)->lport.fabric->vf_id)
4890 
4891 #define BFA_FCS_VPORT_MAX_RETRIES  5
4892 /*
4893  * Forward declarations
4894  */
4895 static void     bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport);
4896 static void     bfa_fcs_vport_timeout(void *vport_arg);
4897 static void     bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport);
4898 static void     bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport);
4899 
4900 /*
4901  *  fcs_vport_sm FCS virtual port state machine
4902  */
4903 
4904 /*
4905  * VPort State Machine events
4906  */
4907 enum bfa_fcs_vport_event {
4908 	BFA_FCS_VPORT_SM_CREATE = 1,	/*  vport create event */
4909 	BFA_FCS_VPORT_SM_DELETE = 2,	/*  vport delete event */
4910 	BFA_FCS_VPORT_SM_START = 3,	/*  vport start request */
4911 	BFA_FCS_VPORT_SM_STOP = 4,	/*  stop: unsupported */
4912 	BFA_FCS_VPORT_SM_ONLINE = 5,	/*  fabric online */
4913 	BFA_FCS_VPORT_SM_OFFLINE = 6,	/*  fabric offline event */
4914 	BFA_FCS_VPORT_SM_FRMSENT = 7,	/*  fdisc/logo sent events */
4915 	BFA_FCS_VPORT_SM_RSP_OK = 8,	/*  good response */
4916 	BFA_FCS_VPORT_SM_RSP_ERROR = 9,	/*  error/bad response */
4917 	BFA_FCS_VPORT_SM_TIMEOUT = 10,	/*  delay timer event */
4918 	BFA_FCS_VPORT_SM_DELCOMP = 11,	/*  lport delete completion */
4919 	BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12,	/*  Dup wnn error*/
4920 	BFA_FCS_VPORT_SM_RSP_FAILED = 13,	/*  non-retryable failure */
4921 };
4922 
4923 static void     bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4924 					enum bfa_fcs_vport_event event);
4925 static void     bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4926 					 enum bfa_fcs_vport_event event);
4927 static void     bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
4928 					 enum bfa_fcs_vport_event event);
4929 static void     bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
4930 				       enum bfa_fcs_vport_event event);
4931 static void     bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
4932 					     enum bfa_fcs_vport_event event);
4933 static void     bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
4934 					enum bfa_fcs_vport_event event);
4935 static void     bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
4936 					  enum bfa_fcs_vport_event event);
4937 static void     bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
4938 					 enum bfa_fcs_vport_event event);
4939 static void     bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
4940 				      enum bfa_fcs_vport_event event);
4941 static void     bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
4942 				      enum bfa_fcs_vport_event event);
4943 
4944 static struct bfa_sm_table_s  vport_sm_table[] = {
4945 	{BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT},
4946 	{BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED},
4947 	{BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE},
4948 	{BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC},
4949 	{BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY},
4950 	{BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE},
4951 	{BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING},
4952 	{BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP},
4953 	{BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO},
4954 	{BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR}
4955 };
4956 
4957 /*
4958  * Beginning state.
4959  */
4960 static void
bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)4961 bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport,
4962 			enum bfa_fcs_vport_event event)
4963 {
4964 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4965 	bfa_trc(__vport_fcs(vport), event);
4966 
4967 	switch (event) {
4968 	case BFA_FCS_VPORT_SM_CREATE:
4969 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_created);
4970 		bfa_fcs_fabric_addvport(__vport_fabric(vport), vport);
4971 		break;
4972 
4973 	default:
4974 		bfa_sm_fault(__vport_fcs(vport), event);
4975 	}
4976 }
4977 
4978 /*
4979  * Created state - a start event is required to start up the state machine.
4980  */
4981 static void
bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)4982 bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport,
4983 			enum bfa_fcs_vport_event event)
4984 {
4985 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
4986 	bfa_trc(__vport_fcs(vport), event);
4987 
4988 	switch (event) {
4989 	case BFA_FCS_VPORT_SM_START:
4990 		if (bfa_sm_cmp_state(__vport_fabric(vport),
4991 					bfa_fcs_fabric_sm_online)
4992 		    && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) {
4993 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
4994 			bfa_fcs_vport_do_fdisc(vport);
4995 		} else {
4996 			/*
4997 			 * Fabric is offline or not NPIV capable, stay in
4998 			 * offline state.
4999 			 */
5000 			vport->vport_stats.fab_no_npiv++;
5001 			bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5002 		}
5003 		break;
5004 
5005 	case BFA_FCS_VPORT_SM_DELETE:
5006 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5007 		bfa_fcs_lport_delete(&vport->lport);
5008 		break;
5009 
5010 	case BFA_FCS_VPORT_SM_ONLINE:
5011 	case BFA_FCS_VPORT_SM_OFFLINE:
5012 		/*
5013 		 * Ignore ONLINE/OFFLINE events from fabric
5014 		 * till vport is started.
5015 		 */
5016 		break;
5017 
5018 	default:
5019 		bfa_sm_fault(__vport_fcs(vport), event);
5020 	}
5021 }
5022 
5023 /*
5024  * Offline state - awaiting ONLINE event from fabric SM.
5025  */
5026 static void
bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5027 bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport,
5028 			enum bfa_fcs_vport_event event)
5029 {
5030 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5031 	bfa_trc(__vport_fcs(vport), event);
5032 
5033 	switch (event) {
5034 	case BFA_FCS_VPORT_SM_DELETE:
5035 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5036 		bfa_fcs_lport_delete(&vport->lport);
5037 		break;
5038 
5039 	case BFA_FCS_VPORT_SM_ONLINE:
5040 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5041 		vport->fdisc_retries = 0;
5042 		bfa_fcs_vport_do_fdisc(vport);
5043 		break;
5044 
5045 	case BFA_FCS_VPORT_SM_OFFLINE:
5046 		/*
5047 		 * This can happen if the vport couldn't be initialzied
5048 		 * due the fact that the npiv was not enabled on the switch.
5049 		 * In that case we will put the vport in offline state.
5050 		 * However, the link can go down and cause the this event to
5051 		 * be sent when we are already offline. Ignore it.
5052 		 */
5053 		break;
5054 
5055 	default:
5056 		bfa_sm_fault(__vport_fcs(vport), event);
5057 	}
5058 }
5059 
5060 
5061 /*
5062  * FDISC is sent and awaiting reply from fabric.
5063  */
5064 static void
bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5065 bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport,
5066 			enum bfa_fcs_vport_event event)
5067 {
5068 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5069 	bfa_trc(__vport_fcs(vport), event);
5070 
5071 	switch (event) {
5072 	case BFA_FCS_VPORT_SM_DELETE:
5073 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5074 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5075 		bfa_fcs_lport_delete(&vport->lport);
5076 		break;
5077 
5078 	case BFA_FCS_VPORT_SM_OFFLINE:
5079 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5080 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5081 		break;
5082 
5083 	case BFA_FCS_VPORT_SM_RSP_OK:
5084 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_online);
5085 		bfa_fcs_lport_online(&vport->lport);
5086 		break;
5087 
5088 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5089 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry);
5090 		bfa_timer_start(__vport_bfa(vport), &vport->timer,
5091 				    bfa_fcs_vport_timeout, vport,
5092 				    BFA_FCS_RETRY_TIMEOUT);
5093 		break;
5094 
5095 	case BFA_FCS_VPORT_SM_RSP_FAILED:
5096 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5097 		break;
5098 
5099 	case BFA_FCS_VPORT_SM_RSP_DUP_WWN:
5100 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_error);
5101 		break;
5102 
5103 	default:
5104 		bfa_sm_fault(__vport_fcs(vport), event);
5105 	}
5106 }
5107 
5108 /*
5109  * FDISC attempt failed - a timer is active to retry FDISC.
5110  */
5111 static void
bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5112 bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport,
5113 			     enum bfa_fcs_vport_event event)
5114 {
5115 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5116 	bfa_trc(__vport_fcs(vport), event);
5117 
5118 	switch (event) {
5119 	case BFA_FCS_VPORT_SM_DELETE:
5120 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5121 		bfa_timer_stop(&vport->timer);
5122 		bfa_fcs_lport_delete(&vport->lport);
5123 		break;
5124 
5125 	case BFA_FCS_VPORT_SM_OFFLINE:
5126 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5127 		bfa_timer_stop(&vport->timer);
5128 		break;
5129 
5130 	case BFA_FCS_VPORT_SM_TIMEOUT:
5131 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc);
5132 		vport->vport_stats.fdisc_retries++;
5133 		vport->fdisc_retries++;
5134 		bfa_fcs_vport_do_fdisc(vport);
5135 		break;
5136 
5137 	default:
5138 		bfa_sm_fault(__vport_fcs(vport), event);
5139 	}
5140 }
5141 
5142 /*
5143  * Vport is online (FDISC is complete).
5144  */
5145 static void
bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5146 bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport,
5147 			enum bfa_fcs_vport_event event)
5148 {
5149 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5150 	bfa_trc(__vport_fcs(vport), event);
5151 
5152 	switch (event) {
5153 	case BFA_FCS_VPORT_SM_DELETE:
5154 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting);
5155 		bfa_fcs_lport_delete(&vport->lport);
5156 		break;
5157 
5158 	case BFA_FCS_VPORT_SM_OFFLINE:
5159 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline);
5160 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5161 		bfa_fcs_lport_offline(&vport->lport);
5162 		break;
5163 
5164 	default:
5165 		bfa_sm_fault(__vport_fcs(vport), event);
5166 	}
5167 }
5168 
5169 /*
5170  * Vport is being deleted - awaiting lport delete completion to send
5171  * LOGO to fabric.
5172  */
5173 static void
bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5174 bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport,
5175 			enum bfa_fcs_vport_event event)
5176 {
5177 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5178 	bfa_trc(__vport_fcs(vport), event);
5179 
5180 	switch (event) {
5181 	case BFA_FCS_VPORT_SM_DELETE:
5182 		break;
5183 
5184 	case BFA_FCS_VPORT_SM_DELCOMP:
5185 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo);
5186 		bfa_fcs_vport_do_logo(vport);
5187 		break;
5188 
5189 	case BFA_FCS_VPORT_SM_OFFLINE:
5190 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5191 		break;
5192 
5193 	default:
5194 		bfa_sm_fault(__vport_fcs(vport), event);
5195 	}
5196 }
5197 
5198 /*
5199  * Error State.
5200  * This state will be set when the Vport Creation fails due
5201  * to errors like Dup WWN. In this state only operation allowed
5202  * is a Vport Delete.
5203  */
5204 static void
bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5205 bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport,
5206 			enum bfa_fcs_vport_event event)
5207 {
5208 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5209 	bfa_trc(__vport_fcs(vport), event);
5210 
5211 	switch (event) {
5212 	case BFA_FCS_VPORT_SM_DELETE:
5213 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup);
5214 		bfa_fcs_lport_delete(&vport->lport);
5215 		break;
5216 
5217 	default:
5218 		bfa_trc(__vport_fcs(vport), event);
5219 	}
5220 }
5221 
5222 /*
5223  * Lport cleanup is in progress since vport is being deleted. Fabric is
5224  * offline, so no LOGO is needed to complete vport deletion.
5225  */
5226 static void
bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5227 bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport,
5228 			enum bfa_fcs_vport_event event)
5229 {
5230 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5231 	bfa_trc(__vport_fcs(vport), event);
5232 
5233 	switch (event) {
5234 	case BFA_FCS_VPORT_SM_DELCOMP:
5235 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5236 		bfa_fcs_vport_free(vport);
5237 		break;
5238 
5239 	case BFA_FCS_VPORT_SM_DELETE:
5240 		break;
5241 
5242 	default:
5243 		bfa_sm_fault(__vport_fcs(vport), event);
5244 	}
5245 }
5246 
5247 /*
5248  * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup
5249  * is done.
5250  */
5251 static void
bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s * vport,enum bfa_fcs_vport_event event)5252 bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport,
5253 			enum bfa_fcs_vport_event event)
5254 {
5255 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5256 	bfa_trc(__vport_fcs(vport), event);
5257 
5258 	switch (event) {
5259 	case BFA_FCS_VPORT_SM_OFFLINE:
5260 		bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE);
5261 		/*
5262 		 * !!! fall through !!!
5263 		 */
5264 
5265 	case BFA_FCS_VPORT_SM_RSP_OK:
5266 	case BFA_FCS_VPORT_SM_RSP_ERROR:
5267 		bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5268 		bfa_fcs_vport_free(vport);
5269 		break;
5270 
5271 	case BFA_FCS_VPORT_SM_DELETE:
5272 		break;
5273 
5274 	default:
5275 		bfa_sm_fault(__vport_fcs(vport), event);
5276 	}
5277 }
5278 
5279 
5280 
5281 /*
5282  *  fcs_vport_private FCS virtual port private functions
5283  */
5284 /*
5285  * This routine will be called to send a FDISC command.
5286  */
5287 static void
bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s * vport)5288 bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport)
5289 {
5290 	bfa_lps_fdisc(vport->lps, vport,
5291 		bfa_fcport_get_maxfrsize(__vport_bfa(vport)),
5292 		__vport_pwwn(vport), __vport_nwwn(vport));
5293 	vport->vport_stats.fdisc_sent++;
5294 }
5295 
5296 static void
bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s * vport)5297 bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport)
5298 {
5299 	u8		lsrjt_rsn = vport->lps->lsrjt_rsn;
5300 	u8		lsrjt_expl = vport->lps->lsrjt_expl;
5301 
5302 	bfa_trc(__vport_fcs(vport), lsrjt_rsn);
5303 	bfa_trc(__vport_fcs(vport), lsrjt_expl);
5304 
5305 	/* For certain reason codes, we don't want to retry. */
5306 	switch (vport->lps->lsrjt_expl) {
5307 	case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */
5308 	case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */
5309 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5310 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5311 		else
5312 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN);
5313 		break;
5314 
5315 	case FC_LS_RJT_EXP_INSUFF_RES:
5316 		/*
5317 		 * This means max logins per port/switch setting on the
5318 		 * switch was exceeded.
5319 		 */
5320 		if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES)
5321 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5322 		else
5323 			bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED);
5324 		break;
5325 
5326 	default:
5327 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5328 	}
5329 }
5330 
5331 /*
5332  *	Called to send a logout to the fabric. Used when a V-Port is
5333  *	deleted/stopped.
5334  */
5335 static void
bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s * vport)5336 bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport)
5337 {
5338 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5339 
5340 	vport->vport_stats.logo_sent++;
5341 	bfa_lps_fdisclogo(vport->lps);
5342 }
5343 
5344 
5345 /*
5346  *     This routine will be called by bfa_timer on timer timeouts.
5347  *
5348  *	param[in]	vport		- pointer to bfa_fcs_vport_t.
5349  *	param[out]	vport_status	- pointer to return vport status in
5350  *
5351  *	return
5352  *		void
5353  *
5354  *	Special Considerations:
5355  *
5356  *	note
5357  */
5358 static void
bfa_fcs_vport_timeout(void * vport_arg)5359 bfa_fcs_vport_timeout(void *vport_arg)
5360 {
5361 	struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *) vport_arg;
5362 
5363 	vport->vport_stats.fdisc_timeouts++;
5364 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT);
5365 }
5366 
5367 static void
bfa_fcs_vport_free(struct bfa_fcs_vport_s * vport)5368 bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport)
5369 {
5370 	struct bfad_vport_s *vport_drv =
5371 			(struct bfad_vport_s *)vport->vport_drv;
5372 
5373 	bfa_fcs_fabric_delvport(__vport_fabric(vport), vport);
5374 
5375 	if (vport_drv->comp_del)
5376 		complete(vport_drv->comp_del);
5377 
5378 	bfa_lps_delete(vport->lps);
5379 }
5380 
5381 
5382 
5383 /*
5384  *  fcs_vport_public FCS virtual port public interfaces
5385  */
5386 
5387 /*
5388  * Online notification from fabric SM.
5389  */
5390 void
bfa_fcs_vport_online(struct bfa_fcs_vport_s * vport)5391 bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport)
5392 {
5393 	vport->vport_stats.fab_online++;
5394 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5395 }
5396 
5397 /*
5398  * Offline notification from fabric SM.
5399  */
5400 void
bfa_fcs_vport_offline(struct bfa_fcs_vport_s * vport)5401 bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport)
5402 {
5403 	vport->vport_stats.fab_offline++;
5404 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5405 }
5406 
5407 /*
5408  * Cleanup notification from fabric SM on link timer expiry.
5409  */
5410 void
bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s * vport)5411 bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport)
5412 {
5413 	vport->vport_stats.fab_cleanup++;
5414 }
5415 /*
5416  * delete notification from fabric SM. To be invoked from within FCS.
5417  */
5418 void
bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s * vport)5419 bfa_fcs_vport_fcs_delete(struct bfa_fcs_vport_s *vport)
5420 {
5421 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5422 }
5423 
5424 /*
5425  * Delete completion callback from associated lport
5426  */
5427 void
bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s * vport)5428 bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport)
5429 {
5430 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP);
5431 }
5432 
5433 
5434 
5435 /*
5436  *  fcs_vport_api Virtual port API
5437  */
5438 
5439 /*
5440  *	Use this function to instantiate a new FCS vport object. This
5441  *	function will not trigger any HW initialization process (which will be
5442  *	done in vport_start() call)
5443  *
5444  *	param[in] vport	-		pointer to bfa_fcs_vport_t. This space
5445  *					needs to be allocated by the driver.
5446  *	param[in] fcs		-	FCS instance
5447  *	param[in] vport_cfg	-	vport configuration
5448  *	param[in] vf_id		-	VF_ID if vport is created within a VF.
5449  *					FC_VF_ID_NULL to specify base fabric.
5450  *	param[in] vport_drv	-	Opaque handle back to the driver's vport
5451  *					structure
5452  *
5453  *	retval BFA_STATUS_OK - on success.
5454  *	retval BFA_STATUS_FAILED - on failure.
5455  */
5456 bfa_status_t
bfa_fcs_vport_create(struct bfa_fcs_vport_s * vport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_lport_cfg_s * vport_cfg,struct bfad_vport_s * vport_drv)5457 bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5458 		u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5459 		struct bfad_vport_s *vport_drv)
5460 {
5461 	if (vport_cfg->pwwn == 0)
5462 		return BFA_STATUS_INVALID_WWN;
5463 
5464 	if (bfa_fcs_lport_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn)
5465 		return BFA_STATUS_VPORT_WWN_BP;
5466 
5467 	if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL)
5468 		return BFA_STATUS_VPORT_EXISTS;
5469 
5470 	if (fcs->fabric.num_vports ==
5471 			bfa_lps_get_max_vport(fcs->bfa))
5472 		return BFA_STATUS_VPORT_MAX;
5473 
5474 	vport->lps = bfa_lps_alloc(fcs->bfa);
5475 	if (!vport->lps)
5476 		return BFA_STATUS_VPORT_MAX;
5477 
5478 	vport->vport_drv = vport_drv;
5479 	vport_cfg->preboot_vp = BFA_FALSE;
5480 
5481 	bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit);
5482 	bfa_fcs_lport_attach(&vport->lport, fcs, vf_id, vport);
5483 	bfa_fcs_lport_init(&vport->lport, vport_cfg);
5484 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE);
5485 
5486 	return BFA_STATUS_OK;
5487 }
5488 
5489 /*
5490  *	Use this function to instantiate a new FCS PBC vport object. This
5491  *	function will not trigger any HW initialization process (which will be
5492  *	done in vport_start() call)
5493  *
5494  *	param[in] vport	-	pointer to bfa_fcs_vport_t. This space
5495  *				needs to be allocated by the driver.
5496  *	param[in] fcs	-	FCS instance
5497  *	param[in] vport_cfg	-	vport configuration
5498  *	param[in] vf_id		-	VF_ID if vport is created within a VF.
5499  *					FC_VF_ID_NULL to specify base fabric.
5500  *	param[in] vport_drv	-	Opaque handle back to the driver's vport
5501  *					structure
5502  *
5503  *	retval BFA_STATUS_OK - on success.
5504  *	retval BFA_STATUS_FAILED - on failure.
5505  */
5506 bfa_status_t
bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s * vport,struct bfa_fcs_s * fcs,u16 vf_id,struct bfa_lport_cfg_s * vport_cfg,struct bfad_vport_s * vport_drv)5507 bfa_fcs_pbc_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs,
5508 			u16 vf_id, struct bfa_lport_cfg_s *vport_cfg,
5509 			struct bfad_vport_s *vport_drv)
5510 {
5511 	bfa_status_t rc;
5512 
5513 	rc = bfa_fcs_vport_create(vport, fcs, vf_id, vport_cfg, vport_drv);
5514 	vport->lport.port_cfg.preboot_vp = BFA_TRUE;
5515 
5516 	return rc;
5517 }
5518 
5519 /*
5520  *	Use this function to findout if this is a pbc vport or not.
5521  *
5522  * @param[in] vport - pointer to bfa_fcs_vport_t.
5523  *
5524  * @returns None
5525  */
5526 bfa_boolean_t
bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s * vport)5527 bfa_fcs_is_pbc_vport(struct bfa_fcs_vport_s *vport)
5528 {
5529 
5530 	if (vport && (vport->lport.port_cfg.preboot_vp == BFA_TRUE))
5531 		return BFA_TRUE;
5532 	else
5533 		return BFA_FALSE;
5534 
5535 }
5536 
5537 /*
5538  * Use this function initialize the vport.
5539  *
5540  * @param[in] vport - pointer to bfa_fcs_vport_t.
5541  *
5542  * @returns None
5543  */
5544 bfa_status_t
bfa_fcs_vport_start(struct bfa_fcs_vport_s * vport)5545 bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport)
5546 {
5547 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START);
5548 
5549 	return BFA_STATUS_OK;
5550 }
5551 
5552 /*
5553  *	Use this function quiese the vport object. This function will return
5554  *	immediately, when the vport is actually stopped, the
5555  *	bfa_drv_vport_stop_cb() will be called.
5556  *
5557  *	param[in] vport - pointer to bfa_fcs_vport_t.
5558  *
5559  *	return None
5560  */
5561 bfa_status_t
bfa_fcs_vport_stop(struct bfa_fcs_vport_s * vport)5562 bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport)
5563 {
5564 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP);
5565 
5566 	return BFA_STATUS_OK;
5567 }
5568 
5569 /*
5570  *	Use this function to delete a vport object. Fabric object should
5571  *	be stopped before this function call.
5572  *
5573  *	!!!!!!! Donot invoke this from within FCS  !!!!!!!
5574  *
5575  *	param[in] vport - pointer to bfa_fcs_vport_t.
5576  *
5577  *	return     None
5578  */
5579 bfa_status_t
bfa_fcs_vport_delete(struct bfa_fcs_vport_s * vport)5580 bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport)
5581 {
5582 
5583 	if (vport->lport.port_cfg.preboot_vp)
5584 		return BFA_STATUS_PBC;
5585 
5586 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE);
5587 
5588 	return BFA_STATUS_OK;
5589 }
5590 
5591 /*
5592  *	Use this function to get vport's current status info.
5593  *
5594  *	param[in] vport		pointer to bfa_fcs_vport_t.
5595  *	param[out] attr		pointer to return vport attributes
5596  *
5597  *	return None
5598  */
5599 void
bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s * vport,struct bfa_vport_attr_s * attr)5600 bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport,
5601 			struct bfa_vport_attr_s *attr)
5602 {
5603 	if (vport == NULL || attr == NULL)
5604 		return;
5605 
5606 	memset(attr, 0, sizeof(struct bfa_vport_attr_s));
5607 
5608 	bfa_fcs_lport_get_attr(&vport->lport, &attr->port_attr);
5609 	attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm);
5610 }
5611 
5612 
5613 /*
5614  *	Lookup a virtual port. Excludes base port from lookup.
5615  */
5616 struct bfa_fcs_vport_s *
bfa_fcs_vport_lookup(struct bfa_fcs_s * fcs,u16 vf_id,wwn_t vpwwn)5617 bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn)
5618 {
5619 	struct bfa_fcs_vport_s *vport;
5620 	struct bfa_fcs_fabric_s *fabric;
5621 
5622 	bfa_trc(fcs, vf_id);
5623 	bfa_trc(fcs, vpwwn);
5624 
5625 	fabric = bfa_fcs_vf_lookup(fcs, vf_id);
5626 	if (!fabric) {
5627 		bfa_trc(fcs, vf_id);
5628 		return NULL;
5629 	}
5630 
5631 	vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn);
5632 	return vport;
5633 }
5634 
5635 /*
5636  * FDISC Response
5637  */
5638 void
bfa_cb_lps_fdisc_comp(void * bfad,void * uarg,bfa_status_t status)5639 bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status)
5640 {
5641 	struct bfa_fcs_vport_s *vport = uarg;
5642 
5643 	bfa_trc(__vport_fcs(vport), __vport_pwwn(vport));
5644 	bfa_trc(__vport_fcs(vport), status);
5645 
5646 	switch (status) {
5647 	case BFA_STATUS_OK:
5648 		/*
5649 		 * Initialize the V-Port fields
5650 		 */
5651 		__vport_fcid(vport) = vport->lps->lp_pid;
5652 		vport->vport_stats.fdisc_accepts++;
5653 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5654 		break;
5655 
5656 	case BFA_STATUS_INVALID_MAC:
5657 		/* Only for CNA */
5658 		vport->vport_stats.fdisc_acc_bad++;
5659 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5660 
5661 		break;
5662 
5663 	case BFA_STATUS_EPROTOCOL:
5664 		switch (vport->lps->ext_status) {
5665 		case BFA_EPROTO_BAD_ACCEPT:
5666 			vport->vport_stats.fdisc_acc_bad++;
5667 			break;
5668 
5669 		case BFA_EPROTO_UNKNOWN_RSP:
5670 			vport->vport_stats.fdisc_unknown_rsp++;
5671 			break;
5672 
5673 		default:
5674 			break;
5675 		}
5676 
5677 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5678 		break;
5679 
5680 	case BFA_STATUS_FABRIC_RJT:
5681 		vport->vport_stats.fdisc_rejects++;
5682 		bfa_fcs_vport_fdisc_rejected(vport);
5683 		break;
5684 
5685 	default:
5686 		vport->vport_stats.fdisc_rsp_err++;
5687 		bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR);
5688 	}
5689 }
5690 
5691 /*
5692  * LOGO response
5693  */
5694 void
bfa_cb_lps_fdisclogo_comp(void * bfad,void * uarg)5695 bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg)
5696 {
5697 	struct bfa_fcs_vport_s *vport = uarg;
5698 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK);
5699 }
5700 
5701 /*
5702  * Received clear virtual link
5703  */
5704 void
bfa_cb_lps_cvl_event(void * bfad,void * uarg)5705 bfa_cb_lps_cvl_event(void *bfad, void *uarg)
5706 {
5707 	struct bfa_fcs_vport_s *vport = uarg;
5708 
5709 	/* Send an Offline followed by an ONLINE */
5710 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE);
5711 	bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE);
5712 }
5713