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