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