xref: /openbmc/linux/drivers/scsi/bfa/bfa_svc.c (revision bbecb07f)
1 /*
2  * Copyright (c) 2005-2014 Brocade Communications Systems, Inc.
3  * Copyright (c) 2014- QLogic Corporation.
4  * All rights reserved
5  * www.qlogic.com
6  *
7  * Linux driver for QLogic BR-series Fibre Channel Host Bus Adapter.
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License (GPL) Version 2 as
11  * published by the Free Software Foundation
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  */
18 
19 #include "bfad_drv.h"
20 #include "bfad_im.h"
21 #include "bfa_plog.h"
22 #include "bfa_cs.h"
23 #include "bfa_modules.h"
24 
25 BFA_TRC_FILE(HAL, FCXP);
26 
27 /*
28  * LPS related definitions
29  */
30 #define BFA_LPS_MIN_LPORTS      (1)
31 #define BFA_LPS_MAX_LPORTS      (256)
32 
33 /*
34  * Maximum Vports supported per physical port or vf.
35  */
36 #define BFA_LPS_MAX_VPORTS_SUPP_CB  255
37 #define BFA_LPS_MAX_VPORTS_SUPP_CT  190
38 
39 
40 /*
41  * FC PORT related definitions
42  */
43 /*
44  * The port is considered disabled if corresponding physical port or IOC are
45  * disabled explicitly
46  */
47 #define BFA_PORT_IS_DISABLED(bfa) \
48 	((bfa_fcport_is_disabled(bfa) == BFA_TRUE) || \
49 	(bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE))
50 
51 /*
52  * BFA port state machine events
53  */
54 enum bfa_fcport_sm_event {
55 	BFA_FCPORT_SM_START	= 1,	/*  start port state machine	*/
56 	BFA_FCPORT_SM_STOP	= 2,	/*  stop port state machine	*/
57 	BFA_FCPORT_SM_ENABLE	= 3,	/*  enable port		*/
58 	BFA_FCPORT_SM_DISABLE	= 4,	/*  disable port state machine */
59 	BFA_FCPORT_SM_FWRSP	= 5,	/*  firmware enable/disable rsp */
60 	BFA_FCPORT_SM_LINKUP	= 6,	/*  firmware linkup event	*/
61 	BFA_FCPORT_SM_LINKDOWN	= 7,	/*  firmware linkup down	*/
62 	BFA_FCPORT_SM_QRESUME	= 8,	/*  CQ space available	*/
63 	BFA_FCPORT_SM_HWFAIL	= 9,	/*  IOC h/w failure		*/
64 	BFA_FCPORT_SM_DPORTENABLE = 10, /*  enable dport      */
65 	BFA_FCPORT_SM_DPORTDISABLE = 11,/*  disable dport     */
66 	BFA_FCPORT_SM_FAA_MISCONFIG = 12,	/* FAA misconfiguratin */
67 	BFA_FCPORT_SM_DDPORTENABLE  = 13,	/* enable ddport	*/
68 	BFA_FCPORT_SM_DDPORTDISABLE = 14,	/* disable ddport	*/
69 };
70 
71 /*
72  * BFA port link notification state machine events
73  */
74 
75 enum bfa_fcport_ln_sm_event {
76 	BFA_FCPORT_LN_SM_LINKUP		= 1,	/*  linkup event	*/
77 	BFA_FCPORT_LN_SM_LINKDOWN	= 2,	/*  linkdown event	*/
78 	BFA_FCPORT_LN_SM_NOTIFICATION	= 3	/*  done notification	*/
79 };
80 
81 /*
82  * RPORT related definitions
83  */
84 #define bfa_rport_offline_cb(__rp) do {					\
85 	if ((__rp)->bfa->fcs)						\
86 		bfa_cb_rport_offline((__rp)->rport_drv);      \
87 	else {								\
88 		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
89 				__bfa_cb_rport_offline, (__rp));      \
90 	}								\
91 } while (0)
92 
93 #define bfa_rport_online_cb(__rp) do {					\
94 	if ((__rp)->bfa->fcs)						\
95 		bfa_cb_rport_online((__rp)->rport_drv);      \
96 	else {								\
97 		bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe,		\
98 				  __bfa_cb_rport_online, (__rp));      \
99 		}							\
100 } while (0)
101 
102 /*
103  * forward declarations FCXP related functions
104  */
105 static void	__bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete);
106 static void	hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
107 				struct bfi_fcxp_send_rsp_s *fcxp_rsp);
108 static void	hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen,
109 				struct bfa_fcxp_s *fcxp, struct fchs_s *fchs);
110 static void	bfa_fcxp_qresume(void *cbarg);
111 static void	bfa_fcxp_queue(struct bfa_fcxp_s *fcxp,
112 				struct bfi_fcxp_send_req_s *send_req);
113 
114 /*
115  * forward declarations for LPS functions
116  */
117 static void bfa_lps_login_rsp(struct bfa_s *bfa,
118 				struct bfi_lps_login_rsp_s *rsp);
119 static void bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count);
120 static void bfa_lps_logout_rsp(struct bfa_s *bfa,
121 				struct bfi_lps_logout_rsp_s *rsp);
122 static void bfa_lps_reqq_resume(void *lps_arg);
123 static void bfa_lps_free(struct bfa_lps_s *lps);
124 static void bfa_lps_send_login(struct bfa_lps_s *lps);
125 static void bfa_lps_send_logout(struct bfa_lps_s *lps);
126 static void bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps);
127 static void bfa_lps_login_comp(struct bfa_lps_s *lps);
128 static void bfa_lps_logout_comp(struct bfa_lps_s *lps);
129 static void bfa_lps_cvl_event(struct bfa_lps_s *lps);
130 
131 /*
132  * forward declaration for LPS state machine
133  */
134 static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event);
135 static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event);
136 static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event
137 					event);
138 static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event);
139 static void bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps,
140 					enum bfa_lps_event event);
141 static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event);
142 static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event
143 					event);
144 
145 /*
146  * forward declaration for FC Port functions
147  */
148 static bfa_boolean_t bfa_fcport_send_enable(struct bfa_fcport_s *fcport);
149 static bfa_boolean_t bfa_fcport_send_disable(struct bfa_fcport_s *fcport);
150 static void bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport);
151 static void bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport);
152 static void bfa_fcport_set_wwns(struct bfa_fcport_s *fcport);
153 static void __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete);
154 static void bfa_fcport_scn(struct bfa_fcport_s *fcport,
155 			enum bfa_port_linkstate event, bfa_boolean_t trunk);
156 static void bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln,
157 				enum bfa_port_linkstate event);
158 static void __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete);
159 static void bfa_fcport_stats_get_timeout(void *cbarg);
160 static void bfa_fcport_stats_clr_timeout(void *cbarg);
161 static void bfa_trunk_iocdisable(struct bfa_s *bfa);
162 
163 /*
164  * forward declaration for FC PORT state machine
165  */
166 static void     bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
167 					enum bfa_fcport_sm_event event);
168 static void     bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
169 					enum bfa_fcport_sm_event event);
170 static void     bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
171 					enum bfa_fcport_sm_event event);
172 static void     bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
173 					enum bfa_fcport_sm_event event);
174 static void     bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
175 					enum bfa_fcport_sm_event event);
176 static void     bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
177 					enum bfa_fcport_sm_event event);
178 static void     bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
179 					enum bfa_fcport_sm_event event);
180 static void     bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
181 					enum bfa_fcport_sm_event event);
182 static void     bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
183 					enum bfa_fcport_sm_event event);
184 static void     bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
185 					enum bfa_fcport_sm_event event);
186 static void     bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
187 					enum bfa_fcport_sm_event event);
188 static void     bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
189 					enum bfa_fcport_sm_event event);
190 static void	bfa_fcport_sm_dport(struct bfa_fcport_s *fcport,
191 					enum bfa_fcport_sm_event event);
192 static void     bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
193 					enum bfa_fcport_sm_event event);
194 static void	bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
195 					enum bfa_fcport_sm_event event);
196 
197 static void     bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
198 					enum bfa_fcport_ln_sm_event event);
199 static void     bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
200 					enum bfa_fcport_ln_sm_event event);
201 static void     bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
202 					enum bfa_fcport_ln_sm_event event);
203 static void     bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
204 					enum bfa_fcport_ln_sm_event event);
205 static void     bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
206 					enum bfa_fcport_ln_sm_event event);
207 static void     bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
208 					enum bfa_fcport_ln_sm_event event);
209 static void     bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
210 					enum bfa_fcport_ln_sm_event event);
211 
212 static struct bfa_sm_table_s hal_port_sm_table[] = {
213 	{BFA_SM(bfa_fcport_sm_uninit), BFA_PORT_ST_UNINIT},
214 	{BFA_SM(bfa_fcport_sm_enabling_qwait), BFA_PORT_ST_ENABLING_QWAIT},
215 	{BFA_SM(bfa_fcport_sm_enabling), BFA_PORT_ST_ENABLING},
216 	{BFA_SM(bfa_fcport_sm_linkdown), BFA_PORT_ST_LINKDOWN},
217 	{BFA_SM(bfa_fcport_sm_linkup), BFA_PORT_ST_LINKUP},
218 	{BFA_SM(bfa_fcport_sm_disabling_qwait), BFA_PORT_ST_DISABLING_QWAIT},
219 	{BFA_SM(bfa_fcport_sm_toggling_qwait), BFA_PORT_ST_TOGGLING_QWAIT},
220 	{BFA_SM(bfa_fcport_sm_disabling), BFA_PORT_ST_DISABLING},
221 	{BFA_SM(bfa_fcport_sm_disabled), BFA_PORT_ST_DISABLED},
222 	{BFA_SM(bfa_fcport_sm_stopped), BFA_PORT_ST_STOPPED},
223 	{BFA_SM(bfa_fcport_sm_iocdown), BFA_PORT_ST_IOCDOWN},
224 	{BFA_SM(bfa_fcport_sm_iocfail), BFA_PORT_ST_IOCDOWN},
225 	{BFA_SM(bfa_fcport_sm_dport), BFA_PORT_ST_DPORT},
226 	{BFA_SM(bfa_fcport_sm_ddport), BFA_PORT_ST_DDPORT},
227 	{BFA_SM(bfa_fcport_sm_faa_misconfig), BFA_PORT_ST_FAA_MISCONFIG},
228 };
229 
230 
231 /*
232  * forward declaration for RPORT related functions
233  */
234 static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod);
235 static void		bfa_rport_free(struct bfa_rport_s *rport);
236 static bfa_boolean_t	bfa_rport_send_fwcreate(struct bfa_rport_s *rp);
237 static bfa_boolean_t	bfa_rport_send_fwdelete(struct bfa_rport_s *rp);
238 static bfa_boolean_t	bfa_rport_send_fwspeed(struct bfa_rport_s *rp);
239 static void		__bfa_cb_rport_online(void *cbarg,
240 						bfa_boolean_t complete);
241 static void		__bfa_cb_rport_offline(void *cbarg,
242 						bfa_boolean_t complete);
243 
244 /*
245  * forward declaration for RPORT state machine
246  */
247 static void     bfa_rport_sm_uninit(struct bfa_rport_s *rp,
248 					enum bfa_rport_event event);
249 static void     bfa_rport_sm_created(struct bfa_rport_s *rp,
250 					enum bfa_rport_event event);
251 static void     bfa_rport_sm_fwcreate(struct bfa_rport_s *rp,
252 					enum bfa_rport_event event);
253 static void     bfa_rport_sm_online(struct bfa_rport_s *rp,
254 					enum bfa_rport_event event);
255 static void     bfa_rport_sm_fwdelete(struct bfa_rport_s *rp,
256 					enum bfa_rport_event event);
257 static void     bfa_rport_sm_offline(struct bfa_rport_s *rp,
258 					enum bfa_rport_event event);
259 static void     bfa_rport_sm_deleting(struct bfa_rport_s *rp,
260 					enum bfa_rport_event event);
261 static void     bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
262 					enum bfa_rport_event event);
263 static void     bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
264 					enum bfa_rport_event event);
265 static void     bfa_rport_sm_iocdisable(struct bfa_rport_s *rp,
266 					enum bfa_rport_event event);
267 static void     bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp,
268 					enum bfa_rport_event event);
269 static void     bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp,
270 					enum bfa_rport_event event);
271 static void     bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp,
272 					enum bfa_rport_event event);
273 
274 /*
275  * PLOG related definitions
276  */
277 static int
278 plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec)
279 {
280 	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
281 		(pl_rec->log_type != BFA_PL_LOG_TYPE_STRING))
282 		return 1;
283 
284 	if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) &&
285 		(pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ))
286 		return 1;
287 
288 	return 0;
289 }
290 
291 static u64
292 bfa_get_log_time(void)
293 {
294 	u64 system_time = 0;
295 	struct timeval tv;
296 	do_gettimeofday(&tv);
297 
298 	/* We are interested in seconds only. */
299 	system_time = tv.tv_sec;
300 	return system_time;
301 }
302 
303 static void
304 bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec)
305 {
306 	u16 tail;
307 	struct bfa_plog_rec_s *pl_recp;
308 
309 	if (plog->plog_enabled == 0)
310 		return;
311 
312 	if (plkd_validate_logrec(pl_rec)) {
313 		WARN_ON(1);
314 		return;
315 	}
316 
317 	tail = plog->tail;
318 
319 	pl_recp = &(plog->plog_recs[tail]);
320 
321 	memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s));
322 
323 	pl_recp->tv = bfa_get_log_time();
324 	BFA_PL_LOG_REC_INCR(plog->tail);
325 
326 	if (plog->head == plog->tail)
327 		BFA_PL_LOG_REC_INCR(plog->head);
328 }
329 
330 void
331 bfa_plog_init(struct bfa_plog_s *plog)
332 {
333 	memset((char *)plog, 0, sizeof(struct bfa_plog_s));
334 
335 	memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN);
336 	plog->head = plog->tail = 0;
337 	plog->plog_enabled = 1;
338 }
339 
340 void
341 bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
342 		enum bfa_plog_eid event,
343 		u16 misc, char *log_str)
344 {
345 	struct bfa_plog_rec_s  lp;
346 
347 	if (plog->plog_enabled) {
348 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
349 		lp.mid = mid;
350 		lp.eid = event;
351 		lp.log_type = BFA_PL_LOG_TYPE_STRING;
352 		lp.misc = misc;
353 		strncpy(lp.log_entry.string_log, log_str,
354 			BFA_PL_STRING_LOG_SZ - 1);
355 		lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0';
356 		bfa_plog_add(plog, &lp);
357 	}
358 }
359 
360 void
361 bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
362 		enum bfa_plog_eid event,
363 		u16 misc, u32 *intarr, u32 num_ints)
364 {
365 	struct bfa_plog_rec_s  lp;
366 	u32 i;
367 
368 	if (num_ints > BFA_PL_INT_LOG_SZ)
369 		num_ints = BFA_PL_INT_LOG_SZ;
370 
371 	if (plog->plog_enabled) {
372 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
373 		lp.mid = mid;
374 		lp.eid = event;
375 		lp.log_type = BFA_PL_LOG_TYPE_INT;
376 		lp.misc = misc;
377 
378 		for (i = 0; i < num_ints; i++)
379 			lp.log_entry.int_log[i] = intarr[i];
380 
381 		lp.log_num_ints = (u8) num_ints;
382 
383 		bfa_plog_add(plog, &lp);
384 	}
385 }
386 
387 void
388 bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
389 			enum bfa_plog_eid event,
390 			u16 misc, struct fchs_s *fchdr)
391 {
392 	struct bfa_plog_rec_s  lp;
393 	u32	*tmp_int = (u32 *) fchdr;
394 	u32	ints[BFA_PL_INT_LOG_SZ];
395 
396 	if (plog->plog_enabled) {
397 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
398 
399 		ints[0] = tmp_int[0];
400 		ints[1] = tmp_int[1];
401 		ints[2] = tmp_int[4];
402 
403 		bfa_plog_intarr(plog, mid, event, misc, ints, 3);
404 	}
405 }
406 
407 void
408 bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid,
409 		      enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr,
410 		      u32 pld_w0)
411 {
412 	struct bfa_plog_rec_s  lp;
413 	u32	*tmp_int = (u32 *) fchdr;
414 	u32	ints[BFA_PL_INT_LOG_SZ];
415 
416 	if (plog->plog_enabled) {
417 		memset(&lp, 0, sizeof(struct bfa_plog_rec_s));
418 
419 		ints[0] = tmp_int[0];
420 		ints[1] = tmp_int[1];
421 		ints[2] = tmp_int[4];
422 		ints[3] = pld_w0;
423 
424 		bfa_plog_intarr(plog, mid, event, misc, ints, 4);
425 	}
426 }
427 
428 
429 /*
430  *  fcxp_pvt BFA FCXP private functions
431  */
432 
433 static void
434 claim_fcxps_mem(struct bfa_fcxp_mod_s *mod)
435 {
436 	u16	i;
437 	struct bfa_fcxp_s *fcxp;
438 
439 	fcxp = (struct bfa_fcxp_s *) bfa_mem_kva_curp(mod);
440 	memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps);
441 
442 	INIT_LIST_HEAD(&mod->fcxp_req_free_q);
443 	INIT_LIST_HEAD(&mod->fcxp_rsp_free_q);
444 	INIT_LIST_HEAD(&mod->fcxp_active_q);
445 	INIT_LIST_HEAD(&mod->fcxp_req_unused_q);
446 	INIT_LIST_HEAD(&mod->fcxp_rsp_unused_q);
447 
448 	mod->fcxp_list = fcxp;
449 
450 	for (i = 0; i < mod->num_fcxps; i++) {
451 		fcxp->fcxp_mod = mod;
452 		fcxp->fcxp_tag = i;
453 
454 		if (i < (mod->num_fcxps / 2)) {
455 			list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
456 			fcxp->req_rsp = BFA_TRUE;
457 		} else {
458 			list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
459 			fcxp->req_rsp = BFA_FALSE;
460 		}
461 
462 		bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp);
463 		fcxp->reqq_waiting = BFA_FALSE;
464 
465 		fcxp = fcxp + 1;
466 	}
467 
468 	bfa_mem_kva_curp(mod) = (void *)fcxp;
469 }
470 
471 void
472 bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
473 		struct bfa_s *bfa)
474 {
475 	struct bfa_fcxp_mod_s *fcxp_mod = BFA_FCXP_MOD(bfa);
476 	struct bfa_mem_kva_s *fcxp_kva = BFA_MEM_FCXP_KVA(bfa);
477 	struct bfa_mem_dma_s *seg_ptr;
478 	u16	nsegs, idx, per_seg_fcxp;
479 	u16	num_fcxps = cfg->fwcfg.num_fcxp_reqs;
480 	u32	per_fcxp_sz;
481 
482 	if (num_fcxps == 0)
483 		return;
484 
485 	if (cfg->drvcfg.min_cfg)
486 		per_fcxp_sz = 2 * BFA_FCXP_MAX_IBUF_SZ;
487 	else
488 		per_fcxp_sz = BFA_FCXP_MAX_IBUF_SZ + BFA_FCXP_MAX_LBUF_SZ;
489 
490 	/* dma memory */
491 	nsegs = BFI_MEM_DMA_NSEGS(num_fcxps, per_fcxp_sz);
492 	per_seg_fcxp = BFI_MEM_NREQS_SEG(per_fcxp_sz);
493 
494 	bfa_mem_dma_seg_iter(fcxp_mod, seg_ptr, nsegs, idx) {
495 		if (num_fcxps >= per_seg_fcxp) {
496 			num_fcxps -= per_seg_fcxp;
497 			bfa_mem_dma_setup(minfo, seg_ptr,
498 				per_seg_fcxp * per_fcxp_sz);
499 		} else
500 			bfa_mem_dma_setup(minfo, seg_ptr,
501 				num_fcxps * per_fcxp_sz);
502 	}
503 
504 	/* kva memory */
505 	bfa_mem_kva_setup(minfo, fcxp_kva,
506 		cfg->fwcfg.num_fcxp_reqs * sizeof(struct bfa_fcxp_s));
507 }
508 
509 void
510 bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
511 		struct bfa_pcidev_s *pcidev)
512 {
513 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
514 
515 	mod->bfa = bfa;
516 	mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs;
517 
518 	/*
519 	 * Initialize FCXP request and response payload sizes.
520 	 */
521 	mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ;
522 	if (!cfg->drvcfg.min_cfg)
523 		mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ;
524 
525 	INIT_LIST_HEAD(&mod->req_wait_q);
526 	INIT_LIST_HEAD(&mod->rsp_wait_q);
527 
528 	claim_fcxps_mem(mod);
529 }
530 
531 void
532 bfa_fcxp_iocdisable(struct bfa_s *bfa)
533 {
534 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
535 	struct bfa_fcxp_s *fcxp;
536 	struct list_head	      *qe, *qen;
537 
538 	/* Enqueue unused fcxp resources to free_q */
539 	list_splice_tail_init(&mod->fcxp_req_unused_q, &mod->fcxp_req_free_q);
540 	list_splice_tail_init(&mod->fcxp_rsp_unused_q, &mod->fcxp_rsp_free_q);
541 
542 	list_for_each_safe(qe, qen, &mod->fcxp_active_q) {
543 		fcxp = (struct bfa_fcxp_s *) qe;
544 		if (fcxp->caller == NULL) {
545 			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
546 					BFA_STATUS_IOC_FAILURE, 0, 0, NULL);
547 			bfa_fcxp_free(fcxp);
548 		} else {
549 			fcxp->rsp_status = BFA_STATUS_IOC_FAILURE;
550 			bfa_cb_queue(bfa, &fcxp->hcb_qe,
551 				     __bfa_fcxp_send_cbfn, fcxp);
552 		}
553 	}
554 }
555 
556 static struct bfa_fcxp_s *
557 bfa_fcxp_get(struct bfa_fcxp_mod_s *fm, bfa_boolean_t req)
558 {
559 	struct bfa_fcxp_s *fcxp;
560 
561 	if (req)
562 		bfa_q_deq(&fm->fcxp_req_free_q, &fcxp);
563 	else
564 		bfa_q_deq(&fm->fcxp_rsp_free_q, &fcxp);
565 
566 	if (fcxp)
567 		list_add_tail(&fcxp->qe, &fm->fcxp_active_q);
568 
569 	return fcxp;
570 }
571 
572 static void
573 bfa_fcxp_init_reqrsp(struct bfa_fcxp_s *fcxp,
574 	       struct bfa_s *bfa,
575 	       u8 *use_ibuf,
576 	       u32 *nr_sgles,
577 	       bfa_fcxp_get_sgaddr_t *r_sga_cbfn,
578 	       bfa_fcxp_get_sglen_t *r_sglen_cbfn,
579 	       struct list_head *r_sgpg_q,
580 	       int n_sgles,
581 	       bfa_fcxp_get_sgaddr_t sga_cbfn,
582 	       bfa_fcxp_get_sglen_t sglen_cbfn)
583 {
584 
585 	WARN_ON(bfa == NULL);
586 
587 	bfa_trc(bfa, fcxp->fcxp_tag);
588 
589 	if (n_sgles == 0) {
590 		*use_ibuf = 1;
591 	} else {
592 		WARN_ON(*sga_cbfn == NULL);
593 		WARN_ON(*sglen_cbfn == NULL);
594 
595 		*use_ibuf = 0;
596 		*r_sga_cbfn = sga_cbfn;
597 		*r_sglen_cbfn = sglen_cbfn;
598 
599 		*nr_sgles = n_sgles;
600 
601 		/*
602 		 * alloc required sgpgs
603 		 */
604 		if (n_sgles > BFI_SGE_INLINE)
605 			WARN_ON(1);
606 	}
607 
608 }
609 
610 static void
611 bfa_fcxp_init(struct bfa_fcxp_s *fcxp,
612 	       void *caller, struct bfa_s *bfa, int nreq_sgles,
613 	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
614 	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
615 	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
616 	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn)
617 {
618 
619 	WARN_ON(bfa == NULL);
620 
621 	bfa_trc(bfa, fcxp->fcxp_tag);
622 
623 	fcxp->caller = caller;
624 
625 	bfa_fcxp_init_reqrsp(fcxp, bfa,
626 		&fcxp->use_ireqbuf, &fcxp->nreq_sgles, &fcxp->req_sga_cbfn,
627 		&fcxp->req_sglen_cbfn, &fcxp->req_sgpg_q,
628 		nreq_sgles, req_sga_cbfn, req_sglen_cbfn);
629 
630 	bfa_fcxp_init_reqrsp(fcxp, bfa,
631 		&fcxp->use_irspbuf, &fcxp->nrsp_sgles, &fcxp->rsp_sga_cbfn,
632 		&fcxp->rsp_sglen_cbfn, &fcxp->rsp_sgpg_q,
633 		nrsp_sgles, rsp_sga_cbfn, rsp_sglen_cbfn);
634 
635 }
636 
637 static void
638 bfa_fcxp_put(struct bfa_fcxp_s *fcxp)
639 {
640 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
641 	struct bfa_fcxp_wqe_s *wqe;
642 
643 	if (fcxp->req_rsp)
644 		bfa_q_deq(&mod->req_wait_q, &wqe);
645 	else
646 		bfa_q_deq(&mod->rsp_wait_q, &wqe);
647 
648 	if (wqe) {
649 		bfa_trc(mod->bfa, fcxp->fcxp_tag);
650 
651 		bfa_fcxp_init(fcxp, wqe->caller, wqe->bfa, wqe->nreq_sgles,
652 			wqe->nrsp_sgles, wqe->req_sga_cbfn,
653 			wqe->req_sglen_cbfn, wqe->rsp_sga_cbfn,
654 			wqe->rsp_sglen_cbfn);
655 
656 		wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp);
657 		return;
658 	}
659 
660 	WARN_ON(!bfa_q_is_on_q(&mod->fcxp_active_q, fcxp));
661 	list_del(&fcxp->qe);
662 
663 	if (fcxp->req_rsp)
664 		list_add_tail(&fcxp->qe, &mod->fcxp_req_free_q);
665 	else
666 		list_add_tail(&fcxp->qe, &mod->fcxp_rsp_free_q);
667 }
668 
669 static void
670 bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg,
671 		   bfa_status_t req_status, u32 rsp_len,
672 		   u32 resid_len, struct fchs_s *rsp_fchs)
673 {
674 	/* discarded fcxp completion */
675 }
676 
677 static void
678 __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete)
679 {
680 	struct bfa_fcxp_s *fcxp = cbarg;
681 
682 	if (complete) {
683 		fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
684 				fcxp->rsp_status, fcxp->rsp_len,
685 				fcxp->residue_len, &fcxp->rsp_fchs);
686 	} else {
687 		bfa_fcxp_free(fcxp);
688 	}
689 }
690 
691 static void
692 hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp)
693 {
694 	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
695 	struct bfa_fcxp_s	*fcxp;
696 	u16		fcxp_tag = be16_to_cpu(fcxp_rsp->fcxp_tag);
697 
698 	bfa_trc(bfa, fcxp_tag);
699 
700 	fcxp_rsp->rsp_len = be32_to_cpu(fcxp_rsp->rsp_len);
701 
702 	/*
703 	 * @todo f/w should not set residue to non-0 when everything
704 	 *	 is received.
705 	 */
706 	if (fcxp_rsp->req_status == BFA_STATUS_OK)
707 		fcxp_rsp->residue_len = 0;
708 	else
709 		fcxp_rsp->residue_len = be32_to_cpu(fcxp_rsp->residue_len);
710 
711 	fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag);
712 
713 	WARN_ON(fcxp->send_cbfn == NULL);
714 
715 	hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp);
716 
717 	if (fcxp->send_cbfn != NULL) {
718 		bfa_trc(mod->bfa, (NULL == fcxp->caller));
719 		if (fcxp->caller == NULL) {
720 			fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg,
721 					fcxp_rsp->req_status, fcxp_rsp->rsp_len,
722 					fcxp_rsp->residue_len, &fcxp_rsp->fchs);
723 			/*
724 			 * fcxp automatically freed on return from the callback
725 			 */
726 			bfa_fcxp_free(fcxp);
727 		} else {
728 			fcxp->rsp_status = fcxp_rsp->req_status;
729 			fcxp->rsp_len = fcxp_rsp->rsp_len;
730 			fcxp->residue_len = fcxp_rsp->residue_len;
731 			fcxp->rsp_fchs = fcxp_rsp->fchs;
732 
733 			bfa_cb_queue(bfa, &fcxp->hcb_qe,
734 					__bfa_fcxp_send_cbfn, fcxp);
735 		}
736 	} else {
737 		bfa_trc(bfa, (NULL == fcxp->send_cbfn));
738 	}
739 }
740 
741 static void
742 hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp,
743 		 struct fchs_s *fchs)
744 {
745 	/*
746 	 * TODO: TX ox_id
747 	 */
748 	if (reqlen > 0) {
749 		if (fcxp->use_ireqbuf) {
750 			u32	pld_w0 =
751 				*((u32 *) BFA_FCXP_REQ_PLD(fcxp));
752 
753 			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
754 					BFA_PL_EID_TX,
755 					reqlen + sizeof(struct fchs_s), fchs,
756 					pld_w0);
757 		} else {
758 			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
759 					BFA_PL_EID_TX,
760 					reqlen + sizeof(struct fchs_s),
761 					fchs);
762 		}
763 	} else {
764 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX,
765 			       reqlen + sizeof(struct fchs_s), fchs);
766 	}
767 }
768 
769 static void
770 hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp,
771 		 struct bfi_fcxp_send_rsp_s *fcxp_rsp)
772 {
773 	if (fcxp_rsp->rsp_len > 0) {
774 		if (fcxp->use_irspbuf) {
775 			u32	pld_w0 =
776 				*((u32 *) BFA_FCXP_RSP_PLD(fcxp));
777 
778 			bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP,
779 					      BFA_PL_EID_RX,
780 					      (u16) fcxp_rsp->rsp_len,
781 					      &fcxp_rsp->fchs, pld_w0);
782 		} else {
783 			bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP,
784 				       BFA_PL_EID_RX,
785 				       (u16) fcxp_rsp->rsp_len,
786 				       &fcxp_rsp->fchs);
787 		}
788 	} else {
789 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX,
790 			       (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs);
791 	}
792 }
793 
794 /*
795  * Handler to resume sending fcxp when space in available in cpe queue.
796  */
797 static void
798 bfa_fcxp_qresume(void *cbarg)
799 {
800 	struct bfa_fcxp_s		*fcxp = cbarg;
801 	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
802 	struct bfi_fcxp_send_req_s	*send_req;
803 
804 	fcxp->reqq_waiting = BFA_FALSE;
805 	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
806 	bfa_fcxp_queue(fcxp, send_req);
807 }
808 
809 /*
810  * Queue fcxp send request to foimrware.
811  */
812 static void
813 bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req)
814 {
815 	struct bfa_s			*bfa = fcxp->fcxp_mod->bfa;
816 	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
817 	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
818 	struct bfa_rport_s		*rport = reqi->bfa_rport;
819 
820 	bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ,
821 		    bfa_fn_lpu(bfa));
822 
823 	send_req->fcxp_tag = cpu_to_be16(fcxp->fcxp_tag);
824 	if (rport) {
825 		send_req->rport_fw_hndl = rport->fw_handle;
826 		send_req->max_frmsz = cpu_to_be16(rport->rport_info.max_frmsz);
827 		if (send_req->max_frmsz == 0)
828 			send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
829 	} else {
830 		send_req->rport_fw_hndl = 0;
831 		send_req->max_frmsz = cpu_to_be16(FC_MAX_PDUSZ);
832 	}
833 
834 	send_req->vf_id = cpu_to_be16(reqi->vf_id);
835 	send_req->lp_fwtag = bfa_lps_get_fwtag(bfa, reqi->lp_tag);
836 	send_req->class = reqi->class;
837 	send_req->rsp_timeout = rspi->rsp_timeout;
838 	send_req->cts = reqi->cts;
839 	send_req->fchs = reqi->fchs;
840 
841 	send_req->req_len = cpu_to_be32(reqi->req_tot_len);
842 	send_req->rsp_maxlen = cpu_to_be32(rspi->rsp_maxlen);
843 
844 	/*
845 	 * setup req sgles
846 	 */
847 	if (fcxp->use_ireqbuf == 1) {
848 		bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
849 					BFA_FCXP_REQ_PLD_PA(fcxp));
850 	} else {
851 		if (fcxp->nreq_sgles > 0) {
852 			WARN_ON(fcxp->nreq_sgles != 1);
853 			bfa_alen_set(&send_req->req_alen, reqi->req_tot_len,
854 				fcxp->req_sga_cbfn(fcxp->caller, 0));
855 		} else {
856 			WARN_ON(reqi->req_tot_len != 0);
857 			bfa_alen_set(&send_req->rsp_alen, 0, 0);
858 		}
859 	}
860 
861 	/*
862 	 * setup rsp sgles
863 	 */
864 	if (fcxp->use_irspbuf == 1) {
865 		WARN_ON(rspi->rsp_maxlen > BFA_FCXP_MAX_LBUF_SZ);
866 
867 		bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
868 					BFA_FCXP_RSP_PLD_PA(fcxp));
869 	} else {
870 		if (fcxp->nrsp_sgles > 0) {
871 			WARN_ON(fcxp->nrsp_sgles != 1);
872 			bfa_alen_set(&send_req->rsp_alen, rspi->rsp_maxlen,
873 				fcxp->rsp_sga_cbfn(fcxp->caller, 0));
874 
875 		} else {
876 			WARN_ON(rspi->rsp_maxlen != 0);
877 			bfa_alen_set(&send_req->rsp_alen, 0, 0);
878 		}
879 	}
880 
881 	hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs);
882 
883 	bfa_reqq_produce(bfa, BFA_REQQ_FCXP, send_req->mh);
884 
885 	bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP));
886 	bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP));
887 }
888 
889 /*
890  * Allocate an FCXP instance to send a response or to send a request
891  * that has a response. Request/response buffers are allocated by caller.
892  *
893  * @param[in]	bfa		BFA bfa instance
894  * @param[in]	nreq_sgles	Number of SG elements required for request
895  *				buffer. 0, if fcxp internal buffers are	used.
896  *				Use bfa_fcxp_get_reqbuf() to get the
897  *				internal req buffer.
898  * @param[in]	req_sgles	SG elements describing request buffer. Will be
899  *				copied in by BFA and hence can be freed on
900  *				return from this function.
901  * @param[in]	get_req_sga	function ptr to be called to get a request SG
902  *				Address (given the sge index).
903  * @param[in]	get_req_sglen	function ptr to be called to get a request SG
904  *				len (given the sge index).
905  * @param[in]	get_rsp_sga	function ptr to be called to get a response SG
906  *				Address (given the sge index).
907  * @param[in]	get_rsp_sglen	function ptr to be called to get a response SG
908  *				len (given the sge index).
909  * @param[in]	req		Allocated FCXP is used to send req or rsp?
910  *				request - BFA_TRUE, response - BFA_FALSE
911  *
912  * @return FCXP instance. NULL on failure.
913  */
914 struct bfa_fcxp_s *
915 bfa_fcxp_req_rsp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles,
916 		int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
917 		bfa_fcxp_get_sglen_t req_sglen_cbfn,
918 		bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
919 		bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
920 {
921 	struct bfa_fcxp_s *fcxp = NULL;
922 
923 	WARN_ON(bfa == NULL);
924 
925 	fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa), req);
926 	if (fcxp == NULL)
927 		return NULL;
928 
929 	bfa_trc(bfa, fcxp->fcxp_tag);
930 
931 	bfa_fcxp_init(fcxp, caller, bfa, nreq_sgles, nrsp_sgles, req_sga_cbfn,
932 			req_sglen_cbfn, rsp_sga_cbfn, rsp_sglen_cbfn);
933 
934 	return fcxp;
935 }
936 
937 /*
938  * Get the internal request buffer pointer
939  *
940  * @param[in]	fcxp	BFA fcxp pointer
941  *
942  * @return		pointer to the internal request buffer
943  */
944 void *
945 bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp)
946 {
947 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
948 	void	*reqbuf;
949 
950 	WARN_ON(fcxp->use_ireqbuf != 1);
951 	reqbuf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
952 				mod->req_pld_sz + mod->rsp_pld_sz);
953 	return reqbuf;
954 }
955 
956 u32
957 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp)
958 {
959 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
960 
961 	return mod->req_pld_sz;
962 }
963 
964 /*
965  * Get the internal response buffer pointer
966  *
967  * @param[in]	fcxp	BFA fcxp pointer
968  *
969  * @return		pointer to the internal request buffer
970  */
971 void *
972 bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp)
973 {
974 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
975 	void	*fcxp_buf;
976 
977 	WARN_ON(fcxp->use_irspbuf != 1);
978 
979 	fcxp_buf = bfa_mem_get_dmabuf_kva(mod, fcxp->fcxp_tag,
980 				mod->req_pld_sz + mod->rsp_pld_sz);
981 
982 	/* fcxp_buf = req_buf + rsp_buf :- add req_buf_sz to get to rsp_buf */
983 	return ((u8 *) fcxp_buf) + mod->req_pld_sz;
984 }
985 
986 /*
987  * Free the BFA FCXP
988  *
989  * @param[in]	fcxp			BFA fcxp pointer
990  *
991  * @return		void
992  */
993 void
994 bfa_fcxp_free(struct bfa_fcxp_s *fcxp)
995 {
996 	struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod;
997 
998 	WARN_ON(fcxp == NULL);
999 	bfa_trc(mod->bfa, fcxp->fcxp_tag);
1000 	bfa_fcxp_put(fcxp);
1001 }
1002 
1003 /*
1004  * Send a FCXP request
1005  *
1006  * @param[in]	fcxp	BFA fcxp pointer
1007  * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
1008  * @param[in]	vf_id	virtual Fabric ID
1009  * @param[in]	lp_tag	lport tag
1010  * @param[in]	cts	use Continuous sequence
1011  * @param[in]	cos	fc Class of Service
1012  * @param[in]	reqlen	request length, does not include FCHS length
1013  * @param[in]	fchs	fc Header Pointer. The header content will be copied
1014  *			in by BFA.
1015  *
1016  * @param[in]	cbfn	call back function to be called on receiving
1017  *								the response
1018  * @param[in]	cbarg	arg for cbfn
1019  * @param[in]	rsp_timeout
1020  *			response timeout
1021  *
1022  * @return		bfa_status_t
1023  */
1024 void
1025 bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport,
1026 	      u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos,
1027 	      u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn,
1028 	      void *cbarg, u32 rsp_maxlen, u8 rsp_timeout)
1029 {
1030 	struct bfa_s			*bfa  = fcxp->fcxp_mod->bfa;
1031 	struct bfa_fcxp_req_info_s	*reqi = &fcxp->req_info;
1032 	struct bfa_fcxp_rsp_info_s	*rspi = &fcxp->rsp_info;
1033 	struct bfi_fcxp_send_req_s	*send_req;
1034 
1035 	bfa_trc(bfa, fcxp->fcxp_tag);
1036 
1037 	/*
1038 	 * setup request/response info
1039 	 */
1040 	reqi->bfa_rport = rport;
1041 	reqi->vf_id = vf_id;
1042 	reqi->lp_tag = lp_tag;
1043 	reqi->class = cos;
1044 	rspi->rsp_timeout = rsp_timeout;
1045 	reqi->cts = cts;
1046 	reqi->fchs = *fchs;
1047 	reqi->req_tot_len = reqlen;
1048 	rspi->rsp_maxlen = rsp_maxlen;
1049 	fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp;
1050 	fcxp->send_cbarg = cbarg;
1051 
1052 	/*
1053 	 * If no room in CPE queue, wait for space in request queue
1054 	 */
1055 	send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP);
1056 	if (!send_req) {
1057 		bfa_trc(bfa, fcxp->fcxp_tag);
1058 		fcxp->reqq_waiting = BFA_TRUE;
1059 		bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe);
1060 		return;
1061 	}
1062 
1063 	bfa_fcxp_queue(fcxp, send_req);
1064 }
1065 
1066 /*
1067  * Abort a BFA FCXP
1068  *
1069  * @param[in]	fcxp	BFA fcxp pointer
1070  *
1071  * @return		void
1072  */
1073 bfa_status_t
1074 bfa_fcxp_abort(struct bfa_fcxp_s *fcxp)
1075 {
1076 	bfa_trc(fcxp->fcxp_mod->bfa, fcxp->fcxp_tag);
1077 	WARN_ON(1);
1078 	return BFA_STATUS_OK;
1079 }
1080 
1081 void
1082 bfa_fcxp_req_rsp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe,
1083 	       bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg,
1084 	       void *caller, int nreq_sgles,
1085 	       int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn,
1086 	       bfa_fcxp_get_sglen_t req_sglen_cbfn,
1087 	       bfa_fcxp_get_sgaddr_t rsp_sga_cbfn,
1088 	       bfa_fcxp_get_sglen_t rsp_sglen_cbfn, bfa_boolean_t req)
1089 {
1090 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1091 
1092 	if (req)
1093 		WARN_ON(!list_empty(&mod->fcxp_req_free_q));
1094 	else
1095 		WARN_ON(!list_empty(&mod->fcxp_rsp_free_q));
1096 
1097 	wqe->alloc_cbfn = alloc_cbfn;
1098 	wqe->alloc_cbarg = alloc_cbarg;
1099 	wqe->caller = caller;
1100 	wqe->bfa = bfa;
1101 	wqe->nreq_sgles = nreq_sgles;
1102 	wqe->nrsp_sgles = nrsp_sgles;
1103 	wqe->req_sga_cbfn = req_sga_cbfn;
1104 	wqe->req_sglen_cbfn = req_sglen_cbfn;
1105 	wqe->rsp_sga_cbfn = rsp_sga_cbfn;
1106 	wqe->rsp_sglen_cbfn = rsp_sglen_cbfn;
1107 
1108 	if (req)
1109 		list_add_tail(&wqe->qe, &mod->req_wait_q);
1110 	else
1111 		list_add_tail(&wqe->qe, &mod->rsp_wait_q);
1112 }
1113 
1114 void
1115 bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe)
1116 {
1117 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1118 
1119 	WARN_ON(!bfa_q_is_on_q(&mod->req_wait_q, wqe) ||
1120 		!bfa_q_is_on_q(&mod->rsp_wait_q, wqe));
1121 	list_del(&wqe->qe);
1122 }
1123 
1124 void
1125 bfa_fcxp_discard(struct bfa_fcxp_s *fcxp)
1126 {
1127 	/*
1128 	 * If waiting for room in request queue, cancel reqq wait
1129 	 * and free fcxp.
1130 	 */
1131 	if (fcxp->reqq_waiting) {
1132 		fcxp->reqq_waiting = BFA_FALSE;
1133 		bfa_reqq_wcancel(&fcxp->reqq_wqe);
1134 		bfa_fcxp_free(fcxp);
1135 		return;
1136 	}
1137 
1138 	fcxp->send_cbfn = bfa_fcxp_null_comp;
1139 }
1140 
1141 void
1142 bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
1143 {
1144 	switch (msg->mhdr.msg_id) {
1145 	case BFI_FCXP_I2H_SEND_RSP:
1146 		hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg);
1147 		break;
1148 
1149 	default:
1150 		bfa_trc(bfa, msg->mhdr.msg_id);
1151 		WARN_ON(1);
1152 	}
1153 }
1154 
1155 u32
1156 bfa_fcxp_get_maxrsp(struct bfa_s *bfa)
1157 {
1158 	struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa);
1159 
1160 	return mod->rsp_pld_sz;
1161 }
1162 
1163 void
1164 bfa_fcxp_res_recfg(struct bfa_s *bfa, u16 num_fcxp_fw)
1165 {
1166 	struct bfa_fcxp_mod_s	*mod = BFA_FCXP_MOD(bfa);
1167 	struct list_head	*qe;
1168 	int	i;
1169 
1170 	for (i = 0; i < (mod->num_fcxps - num_fcxp_fw); i++) {
1171 		if (i < ((mod->num_fcxps - num_fcxp_fw) / 2)) {
1172 			bfa_q_deq_tail(&mod->fcxp_req_free_q, &qe);
1173 			list_add_tail(qe, &mod->fcxp_req_unused_q);
1174 		} else {
1175 			bfa_q_deq_tail(&mod->fcxp_rsp_free_q, &qe);
1176 			list_add_tail(qe, &mod->fcxp_rsp_unused_q);
1177 		}
1178 	}
1179 }
1180 
1181 /*
1182  *  BFA LPS state machine functions
1183  */
1184 
1185 /*
1186  * Init state -- no login
1187  */
1188 static void
1189 bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event)
1190 {
1191 	bfa_trc(lps->bfa, lps->bfa_tag);
1192 	bfa_trc(lps->bfa, event);
1193 
1194 	switch (event) {
1195 	case BFA_LPS_SM_LOGIN:
1196 		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1197 			bfa_sm_set_state(lps, bfa_lps_sm_loginwait);
1198 			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1199 		} else {
1200 			bfa_sm_set_state(lps, bfa_lps_sm_login);
1201 			bfa_lps_send_login(lps);
1202 		}
1203 
1204 		if (lps->fdisc)
1205 			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1206 				BFA_PL_EID_LOGIN, 0, "FDISC Request");
1207 		else
1208 			bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1209 				BFA_PL_EID_LOGIN, 0, "FLOGI Request");
1210 		break;
1211 
1212 	case BFA_LPS_SM_LOGOUT:
1213 		bfa_lps_logout_comp(lps);
1214 		break;
1215 
1216 	case BFA_LPS_SM_DELETE:
1217 		bfa_lps_free(lps);
1218 		break;
1219 
1220 	case BFA_LPS_SM_RX_CVL:
1221 	case BFA_LPS_SM_OFFLINE:
1222 		break;
1223 
1224 	case BFA_LPS_SM_FWRSP:
1225 		/*
1226 		 * Could happen when fabric detects loopback and discards
1227 		 * the lps request. Fw will eventually sent out the timeout
1228 		 * Just ignore
1229 		 */
1230 		break;
1231 	case BFA_LPS_SM_SET_N2N_PID:
1232 		/*
1233 		 * When topology is set to loop, bfa_lps_set_n2n_pid() sends
1234 		 * this event. Ignore this event.
1235 		 */
1236 		break;
1237 
1238 	default:
1239 		bfa_sm_fault(lps->bfa, event);
1240 	}
1241 }
1242 
1243 /*
1244  * login is in progress -- awaiting response from firmware
1245  */
1246 static void
1247 bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event)
1248 {
1249 	bfa_trc(lps->bfa, lps->bfa_tag);
1250 	bfa_trc(lps->bfa, event);
1251 
1252 	switch (event) {
1253 	case BFA_LPS_SM_FWRSP:
1254 		if (lps->status == BFA_STATUS_OK) {
1255 			bfa_sm_set_state(lps, bfa_lps_sm_online);
1256 			if (lps->fdisc)
1257 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1258 					BFA_PL_EID_LOGIN, 0, "FDISC Accept");
1259 			else
1260 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1261 					BFA_PL_EID_LOGIN, 0, "FLOGI Accept");
1262 			/* If N2N, send the assigned PID to FW */
1263 			bfa_trc(lps->bfa, lps->fport);
1264 			bfa_trc(lps->bfa, lps->lp_pid);
1265 
1266 			if (!lps->fport && lps->lp_pid)
1267 				bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1268 		} else {
1269 			bfa_sm_set_state(lps, bfa_lps_sm_init);
1270 			if (lps->fdisc)
1271 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1272 					BFA_PL_EID_LOGIN, 0,
1273 					"FDISC Fail (RJT or timeout)");
1274 			else
1275 				bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1276 					BFA_PL_EID_LOGIN, 0,
1277 					"FLOGI Fail (RJT or timeout)");
1278 		}
1279 		bfa_lps_login_comp(lps);
1280 		break;
1281 
1282 	case BFA_LPS_SM_OFFLINE:
1283 	case BFA_LPS_SM_DELETE:
1284 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1285 		break;
1286 
1287 	case BFA_LPS_SM_SET_N2N_PID:
1288 		bfa_trc(lps->bfa, lps->fport);
1289 		bfa_trc(lps->bfa, lps->lp_pid);
1290 		break;
1291 
1292 	default:
1293 		bfa_sm_fault(lps->bfa, event);
1294 	}
1295 }
1296 
1297 /*
1298  * login pending - awaiting space in request queue
1299  */
1300 static void
1301 bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1302 {
1303 	bfa_trc(lps->bfa, lps->bfa_tag);
1304 	bfa_trc(lps->bfa, event);
1305 
1306 	switch (event) {
1307 	case BFA_LPS_SM_RESUME:
1308 		bfa_sm_set_state(lps, bfa_lps_sm_login);
1309 		bfa_lps_send_login(lps);
1310 		break;
1311 
1312 	case BFA_LPS_SM_OFFLINE:
1313 	case BFA_LPS_SM_DELETE:
1314 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1315 		bfa_reqq_wcancel(&lps->wqe);
1316 		break;
1317 
1318 	case BFA_LPS_SM_RX_CVL:
1319 		/*
1320 		 * Login was not even sent out; so when getting out
1321 		 * of this state, it will appear like a login retry
1322 		 * after Clear virtual link
1323 		 */
1324 		break;
1325 
1326 	default:
1327 		bfa_sm_fault(lps->bfa, event);
1328 	}
1329 }
1330 
1331 /*
1332  * login complete
1333  */
1334 static void
1335 bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event)
1336 {
1337 	bfa_trc(lps->bfa, lps->bfa_tag);
1338 	bfa_trc(lps->bfa, event);
1339 
1340 	switch (event) {
1341 	case BFA_LPS_SM_LOGOUT:
1342 		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1343 			bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1344 			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1345 		} else {
1346 			bfa_sm_set_state(lps, bfa_lps_sm_logout);
1347 			bfa_lps_send_logout(lps);
1348 		}
1349 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1350 			BFA_PL_EID_LOGO, 0, "Logout");
1351 		break;
1352 
1353 	case BFA_LPS_SM_RX_CVL:
1354 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1355 
1356 		/* Let the vport module know about this event */
1357 		bfa_lps_cvl_event(lps);
1358 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1359 			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1360 		break;
1361 
1362 	case BFA_LPS_SM_SET_N2N_PID:
1363 		if (bfa_reqq_full(lps->bfa, lps->reqq)) {
1364 			bfa_sm_set_state(lps, bfa_lps_sm_online_n2n_pid_wait);
1365 			bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe);
1366 		} else
1367 			bfa_lps_send_set_n2n_pid(lps);
1368 		break;
1369 
1370 	case BFA_LPS_SM_OFFLINE:
1371 	case BFA_LPS_SM_DELETE:
1372 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1373 		break;
1374 
1375 	default:
1376 		bfa_sm_fault(lps->bfa, event);
1377 	}
1378 }
1379 
1380 /*
1381  * login complete
1382  */
1383 static void
1384 bfa_lps_sm_online_n2n_pid_wait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1385 {
1386 	bfa_trc(lps->bfa, lps->bfa_tag);
1387 	bfa_trc(lps->bfa, event);
1388 
1389 	switch (event) {
1390 	case BFA_LPS_SM_RESUME:
1391 		bfa_sm_set_state(lps, bfa_lps_sm_online);
1392 		bfa_lps_send_set_n2n_pid(lps);
1393 		break;
1394 
1395 	case BFA_LPS_SM_LOGOUT:
1396 		bfa_sm_set_state(lps, bfa_lps_sm_logowait);
1397 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1398 			BFA_PL_EID_LOGO, 0, "Logout");
1399 		break;
1400 
1401 	case BFA_LPS_SM_RX_CVL:
1402 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1403 		bfa_reqq_wcancel(&lps->wqe);
1404 
1405 		/* Let the vport module know about this event */
1406 		bfa_lps_cvl_event(lps);
1407 		bfa_plog_str(lps->bfa->plog, BFA_PL_MID_LPS,
1408 			BFA_PL_EID_FIP_FCF_CVL, 0, "FCF Clear Virt. Link Rx");
1409 		break;
1410 
1411 	case BFA_LPS_SM_OFFLINE:
1412 	case BFA_LPS_SM_DELETE:
1413 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1414 		bfa_reqq_wcancel(&lps->wqe);
1415 		break;
1416 
1417 	default:
1418 		bfa_sm_fault(lps->bfa, event);
1419 	}
1420 }
1421 
1422 /*
1423  * logout in progress - awaiting firmware response
1424  */
1425 static void
1426 bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event)
1427 {
1428 	bfa_trc(lps->bfa, lps->bfa_tag);
1429 	bfa_trc(lps->bfa, event);
1430 
1431 	switch (event) {
1432 	case BFA_LPS_SM_FWRSP:
1433 	case BFA_LPS_SM_OFFLINE:
1434 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1435 		bfa_lps_logout_comp(lps);
1436 		break;
1437 
1438 	case BFA_LPS_SM_DELETE:
1439 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1440 		break;
1441 
1442 	default:
1443 		bfa_sm_fault(lps->bfa, event);
1444 	}
1445 }
1446 
1447 /*
1448  * logout pending -- awaiting space in request queue
1449  */
1450 static void
1451 bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event)
1452 {
1453 	bfa_trc(lps->bfa, lps->bfa_tag);
1454 	bfa_trc(lps->bfa, event);
1455 
1456 	switch (event) {
1457 	case BFA_LPS_SM_RESUME:
1458 		bfa_sm_set_state(lps, bfa_lps_sm_logout);
1459 		bfa_lps_send_logout(lps);
1460 		break;
1461 
1462 	case BFA_LPS_SM_OFFLINE:
1463 	case BFA_LPS_SM_DELETE:
1464 		bfa_sm_set_state(lps, bfa_lps_sm_init);
1465 		bfa_reqq_wcancel(&lps->wqe);
1466 		break;
1467 
1468 	default:
1469 		bfa_sm_fault(lps->bfa, event);
1470 	}
1471 }
1472 
1473 
1474 
1475 /*
1476  *  lps_pvt BFA LPS private functions
1477  */
1478 
1479 /*
1480  * return memory requirement
1481  */
1482 void
1483 bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
1484 		struct bfa_s *bfa)
1485 {
1486 	struct bfa_mem_kva_s *lps_kva = BFA_MEM_LPS_KVA(bfa);
1487 
1488 	if (cfg->drvcfg.min_cfg)
1489 		bfa_mem_kva_setup(minfo, lps_kva,
1490 			sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS);
1491 	else
1492 		bfa_mem_kva_setup(minfo, lps_kva,
1493 			sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS);
1494 }
1495 
1496 /*
1497  * bfa module attach at initialization time
1498  */
1499 void
1500 bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
1501 	struct bfa_pcidev_s *pcidev)
1502 {
1503 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1504 	struct bfa_lps_s	*lps;
1505 	int			i;
1506 
1507 	mod->num_lps = BFA_LPS_MAX_LPORTS;
1508 	if (cfg->drvcfg.min_cfg)
1509 		mod->num_lps = BFA_LPS_MIN_LPORTS;
1510 	else
1511 		mod->num_lps = BFA_LPS_MAX_LPORTS;
1512 	mod->lps_arr = lps = (struct bfa_lps_s *) bfa_mem_kva_curp(mod);
1513 
1514 	bfa_mem_kva_curp(mod) += mod->num_lps * sizeof(struct bfa_lps_s);
1515 
1516 	INIT_LIST_HEAD(&mod->lps_free_q);
1517 	INIT_LIST_HEAD(&mod->lps_active_q);
1518 	INIT_LIST_HEAD(&mod->lps_login_q);
1519 
1520 	for (i = 0; i < mod->num_lps; i++, lps++) {
1521 		lps->bfa	= bfa;
1522 		lps->bfa_tag	= (u8) i;
1523 		lps->reqq	= BFA_REQQ_LPS;
1524 		bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps);
1525 		list_add_tail(&lps->qe, &mod->lps_free_q);
1526 	}
1527 }
1528 
1529 /*
1530  * IOC in disabled state -- consider all lps offline
1531  */
1532 void
1533 bfa_lps_iocdisable(struct bfa_s *bfa)
1534 {
1535 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1536 	struct bfa_lps_s	*lps;
1537 	struct list_head		*qe, *qen;
1538 
1539 	list_for_each_safe(qe, qen, &mod->lps_active_q) {
1540 		lps = (struct bfa_lps_s *) qe;
1541 		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1542 	}
1543 	list_for_each_safe(qe, qen, &mod->lps_login_q) {
1544 		lps = (struct bfa_lps_s *) qe;
1545 		bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE);
1546 	}
1547 	list_splice_tail_init(&mod->lps_login_q, &mod->lps_active_q);
1548 }
1549 
1550 /*
1551  * Firmware login response
1552  */
1553 static void
1554 bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp)
1555 {
1556 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1557 	struct bfa_lps_s	*lps;
1558 
1559 	WARN_ON(rsp->bfa_tag >= mod->num_lps);
1560 	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1561 
1562 	lps->status = rsp->status;
1563 	switch (rsp->status) {
1564 	case BFA_STATUS_OK:
1565 		lps->fw_tag	= rsp->fw_tag;
1566 		lps->fport	= rsp->f_port;
1567 		if (lps->fport)
1568 			lps->lp_pid = rsp->lp_pid;
1569 		lps->npiv_en	= rsp->npiv_en;
1570 		lps->pr_bbcred	= be16_to_cpu(rsp->bb_credit);
1571 		lps->pr_pwwn	= rsp->port_name;
1572 		lps->pr_nwwn	= rsp->node_name;
1573 		lps->auth_req	= rsp->auth_req;
1574 		lps->lp_mac	= rsp->lp_mac;
1575 		lps->brcd_switch = rsp->brcd_switch;
1576 		lps->fcf_mac	= rsp->fcf_mac;
1577 
1578 		break;
1579 
1580 	case BFA_STATUS_FABRIC_RJT:
1581 		lps->lsrjt_rsn = rsp->lsrjt_rsn;
1582 		lps->lsrjt_expl = rsp->lsrjt_expl;
1583 
1584 		break;
1585 
1586 	case BFA_STATUS_EPROTOCOL:
1587 		lps->ext_status = rsp->ext_status;
1588 
1589 		break;
1590 
1591 	case BFA_STATUS_VPORT_MAX:
1592 		if (rsp->ext_status)
1593 			bfa_lps_no_res(lps, rsp->ext_status);
1594 		break;
1595 
1596 	default:
1597 		/* Nothing to do with other status */
1598 		break;
1599 	}
1600 
1601 	list_del(&lps->qe);
1602 	list_add_tail(&lps->qe, &mod->lps_active_q);
1603 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1604 }
1605 
1606 static void
1607 bfa_lps_no_res(struct bfa_lps_s *first_lps, u8 count)
1608 {
1609 	struct bfa_s		*bfa = first_lps->bfa;
1610 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1611 	struct list_head	*qe, *qe_next;
1612 	struct bfa_lps_s	*lps;
1613 
1614 	bfa_trc(bfa, count);
1615 
1616 	qe = bfa_q_next(first_lps);
1617 
1618 	while (count && qe) {
1619 		qe_next = bfa_q_next(qe);
1620 		lps = (struct bfa_lps_s *)qe;
1621 		bfa_trc(bfa, lps->bfa_tag);
1622 		lps->status = first_lps->status;
1623 		list_del(&lps->qe);
1624 		list_add_tail(&lps->qe, &mod->lps_active_q);
1625 		bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1626 		qe = qe_next;
1627 		count--;
1628 	}
1629 }
1630 
1631 /*
1632  * Firmware logout response
1633  */
1634 static void
1635 bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp)
1636 {
1637 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1638 	struct bfa_lps_s	*lps;
1639 
1640 	WARN_ON(rsp->bfa_tag >= mod->num_lps);
1641 	lps = BFA_LPS_FROM_TAG(mod, rsp->bfa_tag);
1642 
1643 	bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP);
1644 }
1645 
1646 /*
1647  * Firmware received a Clear virtual link request (for FCoE)
1648  */
1649 static void
1650 bfa_lps_rx_cvl_event(struct bfa_s *bfa, struct bfi_lps_cvl_event_s *cvl)
1651 {
1652 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1653 	struct bfa_lps_s	*lps;
1654 
1655 	lps = BFA_LPS_FROM_TAG(mod, cvl->bfa_tag);
1656 
1657 	bfa_sm_send_event(lps, BFA_LPS_SM_RX_CVL);
1658 }
1659 
1660 /*
1661  * Space is available in request queue, resume queueing request to firmware.
1662  */
1663 static void
1664 bfa_lps_reqq_resume(void *lps_arg)
1665 {
1666 	struct bfa_lps_s	*lps = lps_arg;
1667 
1668 	bfa_sm_send_event(lps, BFA_LPS_SM_RESUME);
1669 }
1670 
1671 /*
1672  * lps is freed -- triggered by vport delete
1673  */
1674 static void
1675 bfa_lps_free(struct bfa_lps_s *lps)
1676 {
1677 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
1678 
1679 	lps->lp_pid = 0;
1680 	list_del(&lps->qe);
1681 	list_add_tail(&lps->qe, &mod->lps_free_q);
1682 }
1683 
1684 /*
1685  * send login request to firmware
1686  */
1687 static void
1688 bfa_lps_send_login(struct bfa_lps_s *lps)
1689 {
1690 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(lps->bfa);
1691 	struct bfi_lps_login_req_s	*m;
1692 
1693 	m = bfa_reqq_next(lps->bfa, lps->reqq);
1694 	WARN_ON(!m);
1695 
1696 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ,
1697 		bfa_fn_lpu(lps->bfa));
1698 
1699 	m->bfa_tag	= lps->bfa_tag;
1700 	m->alpa		= lps->alpa;
1701 	m->pdu_size	= cpu_to_be16(lps->pdusz);
1702 	m->pwwn		= lps->pwwn;
1703 	m->nwwn		= lps->nwwn;
1704 	m->fdisc	= lps->fdisc;
1705 	m->auth_en	= lps->auth_en;
1706 
1707 	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1708 	list_del(&lps->qe);
1709 	list_add_tail(&lps->qe, &mod->lps_login_q);
1710 }
1711 
1712 /*
1713  * send logout request to firmware
1714  */
1715 static void
1716 bfa_lps_send_logout(struct bfa_lps_s *lps)
1717 {
1718 	struct bfi_lps_logout_req_s *m;
1719 
1720 	m = bfa_reqq_next(lps->bfa, lps->reqq);
1721 	WARN_ON(!m);
1722 
1723 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ,
1724 		bfa_fn_lpu(lps->bfa));
1725 
1726 	m->fw_tag = lps->fw_tag;
1727 	m->port_name = lps->pwwn;
1728 	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1729 }
1730 
1731 /*
1732  * send n2n pid set request to firmware
1733  */
1734 static void
1735 bfa_lps_send_set_n2n_pid(struct bfa_lps_s *lps)
1736 {
1737 	struct bfi_lps_n2n_pid_req_s *m;
1738 
1739 	m = bfa_reqq_next(lps->bfa, lps->reqq);
1740 	WARN_ON(!m);
1741 
1742 	bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_N2N_PID_REQ,
1743 		bfa_fn_lpu(lps->bfa));
1744 
1745 	m->fw_tag = lps->fw_tag;
1746 	m->lp_pid = lps->lp_pid;
1747 	bfa_reqq_produce(lps->bfa, lps->reqq, m->mh);
1748 }
1749 
1750 /*
1751  * Indirect login completion handler for non-fcs
1752  */
1753 static void
1754 bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete)
1755 {
1756 	struct bfa_lps_s *lps	= arg;
1757 
1758 	if (!complete)
1759 		return;
1760 
1761 	if (lps->fdisc)
1762 		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1763 	else
1764 		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1765 }
1766 
1767 /*
1768  * Login completion handler -- direct call for fcs, queue for others
1769  */
1770 static void
1771 bfa_lps_login_comp(struct bfa_lps_s *lps)
1772 {
1773 	if (!lps->bfa->fcs) {
1774 		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_login_comp_cb,
1775 			lps);
1776 		return;
1777 	}
1778 
1779 	if (lps->fdisc)
1780 		bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status);
1781 	else
1782 		bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status);
1783 }
1784 
1785 /*
1786  * Indirect logout completion handler for non-fcs
1787  */
1788 static void
1789 bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete)
1790 {
1791 	struct bfa_lps_s *lps	= arg;
1792 
1793 	if (!complete)
1794 		return;
1795 
1796 	if (lps->fdisc)
1797 		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1798 	else
1799 		bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg);
1800 }
1801 
1802 /*
1803  * Logout completion handler -- direct call for fcs, queue for others
1804  */
1805 static void
1806 bfa_lps_logout_comp(struct bfa_lps_s *lps)
1807 {
1808 	if (!lps->bfa->fcs) {
1809 		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_logout_comp_cb,
1810 			lps);
1811 		return;
1812 	}
1813 	if (lps->fdisc)
1814 		bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg);
1815 }
1816 
1817 /*
1818  * Clear virtual link completion handler for non-fcs
1819  */
1820 static void
1821 bfa_lps_cvl_event_cb(void *arg, bfa_boolean_t complete)
1822 {
1823 	struct bfa_lps_s *lps	= arg;
1824 
1825 	if (!complete)
1826 		return;
1827 
1828 	/* Clear virtual link to base port will result in link down */
1829 	if (lps->fdisc)
1830 		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1831 }
1832 
1833 /*
1834  * Received Clear virtual link event --direct call for fcs,
1835  * queue for others
1836  */
1837 static void
1838 bfa_lps_cvl_event(struct bfa_lps_s *lps)
1839 {
1840 	if (!lps->bfa->fcs) {
1841 		bfa_cb_queue(lps->bfa, &lps->hcb_qe, bfa_lps_cvl_event_cb,
1842 			lps);
1843 		return;
1844 	}
1845 
1846 	/* Clear virtual link to base port will result in link down */
1847 	if (lps->fdisc)
1848 		bfa_cb_lps_cvl_event(lps->bfa->bfad, lps->uarg);
1849 }
1850 
1851 
1852 
1853 /*
1854  *  lps_public BFA LPS public functions
1855  */
1856 
1857 u32
1858 bfa_lps_get_max_vport(struct bfa_s *bfa)
1859 {
1860 	if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT)
1861 		return BFA_LPS_MAX_VPORTS_SUPP_CT;
1862 	else
1863 		return BFA_LPS_MAX_VPORTS_SUPP_CB;
1864 }
1865 
1866 /*
1867  * Allocate a lport srvice tag.
1868  */
1869 struct bfa_lps_s  *
1870 bfa_lps_alloc(struct bfa_s *bfa)
1871 {
1872 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1873 	struct bfa_lps_s	*lps = NULL;
1874 
1875 	bfa_q_deq(&mod->lps_free_q, &lps);
1876 
1877 	if (lps == NULL)
1878 		return NULL;
1879 
1880 	list_add_tail(&lps->qe, &mod->lps_active_q);
1881 
1882 	bfa_sm_set_state(lps, bfa_lps_sm_init);
1883 	return lps;
1884 }
1885 
1886 /*
1887  * Free lport service tag. This can be called anytime after an alloc.
1888  * No need to wait for any pending login/logout completions.
1889  */
1890 void
1891 bfa_lps_delete(struct bfa_lps_s *lps)
1892 {
1893 	bfa_sm_send_event(lps, BFA_LPS_SM_DELETE);
1894 }
1895 
1896 /*
1897  * Initiate a lport login.
1898  */
1899 void
1900 bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz,
1901 	wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en)
1902 {
1903 	lps->uarg	= uarg;
1904 	lps->alpa	= alpa;
1905 	lps->pdusz	= pdusz;
1906 	lps->pwwn	= pwwn;
1907 	lps->nwwn	= nwwn;
1908 	lps->fdisc	= BFA_FALSE;
1909 	lps->auth_en	= auth_en;
1910 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1911 }
1912 
1913 /*
1914  * Initiate a lport fdisc login.
1915  */
1916 void
1917 bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn,
1918 	wwn_t nwwn)
1919 {
1920 	lps->uarg	= uarg;
1921 	lps->alpa	= 0;
1922 	lps->pdusz	= pdusz;
1923 	lps->pwwn	= pwwn;
1924 	lps->nwwn	= nwwn;
1925 	lps->fdisc	= BFA_TRUE;
1926 	lps->auth_en	= BFA_FALSE;
1927 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN);
1928 }
1929 
1930 
1931 /*
1932  * Initiate a lport FDSIC logout.
1933  */
1934 void
1935 bfa_lps_fdisclogo(struct bfa_lps_s *lps)
1936 {
1937 	bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT);
1938 }
1939 
1940 u8
1941 bfa_lps_get_fwtag(struct bfa_s *bfa, u8 lp_tag)
1942 {
1943 	struct bfa_lps_mod_s    *mod = BFA_LPS_MOD(bfa);
1944 
1945 	return BFA_LPS_FROM_TAG(mod, lp_tag)->fw_tag;
1946 }
1947 
1948 /*
1949  * Return lport services tag given the pid
1950  */
1951 u8
1952 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid)
1953 {
1954 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1955 	struct bfa_lps_s	*lps;
1956 	int			i;
1957 
1958 	for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) {
1959 		if (lps->lp_pid == pid)
1960 			return lps->bfa_tag;
1961 	}
1962 
1963 	/* Return base port tag anyway */
1964 	return 0;
1965 }
1966 
1967 
1968 /*
1969  * return port id assigned to the base lport
1970  */
1971 u32
1972 bfa_lps_get_base_pid(struct bfa_s *bfa)
1973 {
1974 	struct bfa_lps_mod_s	*mod = BFA_LPS_MOD(bfa);
1975 
1976 	return BFA_LPS_FROM_TAG(mod, 0)->lp_pid;
1977 }
1978 
1979 /*
1980  * Set PID in case of n2n (which is assigned during PLOGI)
1981  */
1982 void
1983 bfa_lps_set_n2n_pid(struct bfa_lps_s *lps, uint32_t n2n_pid)
1984 {
1985 	bfa_trc(lps->bfa, lps->bfa_tag);
1986 	bfa_trc(lps->bfa, n2n_pid);
1987 
1988 	lps->lp_pid = n2n_pid;
1989 	bfa_sm_send_event(lps, BFA_LPS_SM_SET_N2N_PID);
1990 }
1991 
1992 /*
1993  * LPS firmware message class handler.
1994  */
1995 void
1996 bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
1997 {
1998 	union bfi_lps_i2h_msg_u	msg;
1999 
2000 	bfa_trc(bfa, m->mhdr.msg_id);
2001 	msg.msg = m;
2002 
2003 	switch (m->mhdr.msg_id) {
2004 	case BFI_LPS_I2H_LOGIN_RSP:
2005 		bfa_lps_login_rsp(bfa, msg.login_rsp);
2006 		break;
2007 
2008 	case BFI_LPS_I2H_LOGOUT_RSP:
2009 		bfa_lps_logout_rsp(bfa, msg.logout_rsp);
2010 		break;
2011 
2012 	case BFI_LPS_I2H_CVL_EVENT:
2013 		bfa_lps_rx_cvl_event(bfa, msg.cvl_event);
2014 		break;
2015 
2016 	default:
2017 		bfa_trc(bfa, m->mhdr.msg_id);
2018 		WARN_ON(1);
2019 	}
2020 }
2021 
2022 static void
2023 bfa_fcport_aen_post(struct bfa_fcport_s *fcport, enum bfa_port_aen_event event)
2024 {
2025 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2026 	struct bfa_aen_entry_s  *aen_entry;
2027 
2028 	bfad_get_aen_entry(bfad, aen_entry);
2029 	if (!aen_entry)
2030 		return;
2031 
2032 	aen_entry->aen_data.port.ioc_type = bfa_get_type(fcport->bfa);
2033 	aen_entry->aen_data.port.pwwn = fcport->pwwn;
2034 
2035 	/* Send the AEN notification */
2036 	bfad_im_post_vendor_event(aen_entry, bfad, ++fcport->bfa->bfa_aen_seq,
2037 				  BFA_AEN_CAT_PORT, event);
2038 }
2039 
2040 /*
2041  * FC PORT state machine functions
2042  */
2043 static void
2044 bfa_fcport_sm_uninit(struct bfa_fcport_s *fcport,
2045 			enum bfa_fcport_sm_event event)
2046 {
2047 	bfa_trc(fcport->bfa, event);
2048 
2049 	switch (event) {
2050 	case BFA_FCPORT_SM_START:
2051 		/*
2052 		 * Start event after IOC is configured and BFA is started.
2053 		 */
2054 		fcport->use_flash_cfg = BFA_TRUE;
2055 
2056 		if (bfa_fcport_send_enable(fcport)) {
2057 			bfa_trc(fcport->bfa, BFA_TRUE);
2058 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2059 		} else {
2060 			bfa_trc(fcport->bfa, BFA_FALSE);
2061 			bfa_sm_set_state(fcport,
2062 					bfa_fcport_sm_enabling_qwait);
2063 		}
2064 		break;
2065 
2066 	case BFA_FCPORT_SM_ENABLE:
2067 		/*
2068 		 * Port is persistently configured to be in enabled state. Do
2069 		 * not change state. Port enabling is done when START event is
2070 		 * received.
2071 		 */
2072 		break;
2073 
2074 	case BFA_FCPORT_SM_DISABLE:
2075 		/*
2076 		 * If a port is persistently configured to be disabled, the
2077 		 * first event will a port disable request.
2078 		 */
2079 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2080 		break;
2081 
2082 	case BFA_FCPORT_SM_HWFAIL:
2083 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2084 		break;
2085 
2086 	default:
2087 		bfa_sm_fault(fcport->bfa, event);
2088 	}
2089 }
2090 
2091 static void
2092 bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
2093 				enum bfa_fcport_sm_event event)
2094 {
2095 	char pwwn_buf[BFA_STRING_32];
2096 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2097 	bfa_trc(fcport->bfa, event);
2098 
2099 	switch (event) {
2100 	case BFA_FCPORT_SM_QRESUME:
2101 		bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2102 		bfa_fcport_send_enable(fcport);
2103 		break;
2104 
2105 	case BFA_FCPORT_SM_STOP:
2106 		bfa_reqq_wcancel(&fcport->reqq_wait);
2107 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2108 		break;
2109 
2110 	case BFA_FCPORT_SM_ENABLE:
2111 		/*
2112 		 * Already enable is in progress.
2113 		 */
2114 		break;
2115 
2116 	case BFA_FCPORT_SM_DISABLE:
2117 		/*
2118 		 * Just send disable request to firmware when room becomes
2119 		 * available in request queue.
2120 		 */
2121 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2122 		bfa_reqq_wcancel(&fcport->reqq_wait);
2123 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2124 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2125 		wwn2str(pwwn_buf, fcport->pwwn);
2126 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2127 			"Base port disabled: WWN = %s\n", pwwn_buf);
2128 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2129 		break;
2130 
2131 	case BFA_FCPORT_SM_LINKUP:
2132 	case BFA_FCPORT_SM_LINKDOWN:
2133 		/*
2134 		 * Possible to get link events when doing back-to-back
2135 		 * enable/disables.
2136 		 */
2137 		break;
2138 
2139 	case BFA_FCPORT_SM_HWFAIL:
2140 		bfa_reqq_wcancel(&fcport->reqq_wait);
2141 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2142 		break;
2143 
2144 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2145 		bfa_fcport_reset_linkinfo(fcport);
2146 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2147 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2148 		break;
2149 
2150 	default:
2151 		bfa_sm_fault(fcport->bfa, event);
2152 	}
2153 }
2154 
2155 static void
2156 bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
2157 						enum bfa_fcport_sm_event event)
2158 {
2159 	char pwwn_buf[BFA_STRING_32];
2160 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2161 	bfa_trc(fcport->bfa, event);
2162 
2163 	switch (event) {
2164 	case BFA_FCPORT_SM_FWRSP:
2165 	case BFA_FCPORT_SM_LINKDOWN:
2166 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2167 		break;
2168 
2169 	case BFA_FCPORT_SM_LINKUP:
2170 		bfa_fcport_update_linkinfo(fcport);
2171 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2172 
2173 		WARN_ON(!fcport->event_cbfn);
2174 		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2175 		break;
2176 
2177 	case BFA_FCPORT_SM_ENABLE:
2178 		/*
2179 		 * Already being enabled.
2180 		 */
2181 		break;
2182 
2183 	case BFA_FCPORT_SM_DISABLE:
2184 		if (bfa_fcport_send_disable(fcport))
2185 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2186 		else
2187 			bfa_sm_set_state(fcport,
2188 					 bfa_fcport_sm_disabling_qwait);
2189 
2190 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2191 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2192 		wwn2str(pwwn_buf, fcport->pwwn);
2193 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2194 			"Base port disabled: WWN = %s\n", pwwn_buf);
2195 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2196 		break;
2197 
2198 	case BFA_FCPORT_SM_STOP:
2199 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2200 		break;
2201 
2202 	case BFA_FCPORT_SM_HWFAIL:
2203 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2204 		break;
2205 
2206 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2207 		bfa_fcport_reset_linkinfo(fcport);
2208 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2209 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2210 		break;
2211 
2212 	default:
2213 		bfa_sm_fault(fcport->bfa, event);
2214 	}
2215 }
2216 
2217 static void
2218 bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
2219 						enum bfa_fcport_sm_event event)
2220 {
2221 	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
2222 	char pwwn_buf[BFA_STRING_32];
2223 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2224 
2225 	bfa_trc(fcport->bfa, event);
2226 
2227 	switch (event) {
2228 	case BFA_FCPORT_SM_LINKUP:
2229 		bfa_fcport_update_linkinfo(fcport);
2230 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkup);
2231 		WARN_ON(!fcport->event_cbfn);
2232 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2233 				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup");
2234 		if (!bfa_ioc_get_fcmode(&fcport->bfa->ioc)) {
2235 
2236 			bfa_trc(fcport->bfa,
2237 				pevent->link_state.attr.vc_fcf.fcf.fipenabled);
2238 			bfa_trc(fcport->bfa,
2239 				pevent->link_state.attr.vc_fcf.fcf.fipfailed);
2240 
2241 			if (pevent->link_state.attr.vc_fcf.fcf.fipfailed)
2242 				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2243 					BFA_PL_EID_FIP_FCF_DISC, 0,
2244 					"FIP FCF Discovery Failed");
2245 			else
2246 				bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2247 					BFA_PL_EID_FIP_FCF_DISC, 0,
2248 					"FIP FCF Discovered");
2249 		}
2250 
2251 		bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
2252 		wwn2str(pwwn_buf, fcport->pwwn);
2253 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2254 			"Base port online: WWN = %s\n", pwwn_buf);
2255 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ONLINE);
2256 
2257 		/* If QoS is enabled and it is not online, send AEN */
2258 		if (fcport->cfg.qos_enabled &&
2259 		    fcport->qos_attr.state != BFA_QOS_ONLINE)
2260 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_QOS_NEG);
2261 		break;
2262 
2263 	case BFA_FCPORT_SM_LINKDOWN:
2264 		/*
2265 		 * Possible to get link down event.
2266 		 */
2267 		break;
2268 
2269 	case BFA_FCPORT_SM_ENABLE:
2270 		/*
2271 		 * Already enabled.
2272 		 */
2273 		break;
2274 
2275 	case BFA_FCPORT_SM_DISABLE:
2276 		if (bfa_fcport_send_disable(fcport))
2277 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2278 		else
2279 			bfa_sm_set_state(fcport,
2280 					 bfa_fcport_sm_disabling_qwait);
2281 
2282 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2283 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2284 		wwn2str(pwwn_buf, fcport->pwwn);
2285 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2286 			"Base port disabled: WWN = %s\n", pwwn_buf);
2287 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2288 		break;
2289 
2290 	case BFA_FCPORT_SM_STOP:
2291 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2292 		break;
2293 
2294 	case BFA_FCPORT_SM_HWFAIL:
2295 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2296 		break;
2297 
2298 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2299 		bfa_fcport_reset_linkinfo(fcport);
2300 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2301 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2302 		break;
2303 
2304 	default:
2305 		bfa_sm_fault(fcport->bfa, event);
2306 	}
2307 }
2308 
2309 static void
2310 bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
2311 	enum bfa_fcport_sm_event event)
2312 {
2313 	char pwwn_buf[BFA_STRING_32];
2314 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2315 
2316 	bfa_trc(fcport->bfa, event);
2317 
2318 	switch (event) {
2319 	case BFA_FCPORT_SM_ENABLE:
2320 		/*
2321 		 * Already enabled.
2322 		 */
2323 		break;
2324 
2325 	case BFA_FCPORT_SM_DISABLE:
2326 		if (bfa_fcport_send_disable(fcport))
2327 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2328 		else
2329 			bfa_sm_set_state(fcport,
2330 					 bfa_fcport_sm_disabling_qwait);
2331 
2332 		bfa_fcport_reset_linkinfo(fcport);
2333 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2334 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2335 				BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2336 		wwn2str(pwwn_buf, fcport->pwwn);
2337 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2338 			"Base port offline: WWN = %s\n", pwwn_buf);
2339 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2340 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2341 			"Base port disabled: WWN = %s\n", pwwn_buf);
2342 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2343 		break;
2344 
2345 	case BFA_FCPORT_SM_LINKDOWN:
2346 		bfa_sm_set_state(fcport, bfa_fcport_sm_linkdown);
2347 		bfa_fcport_reset_linkinfo(fcport);
2348 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2349 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2350 				BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
2351 		wwn2str(pwwn_buf, fcport->pwwn);
2352 		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2353 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2354 				"Base port offline: WWN = %s\n", pwwn_buf);
2355 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2356 		} else {
2357 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2358 				"Base port (WWN = %s) "
2359 				"lost fabric connectivity\n", pwwn_buf);
2360 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2361 		}
2362 		break;
2363 
2364 	case BFA_FCPORT_SM_STOP:
2365 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2366 		bfa_fcport_reset_linkinfo(fcport);
2367 		wwn2str(pwwn_buf, fcport->pwwn);
2368 		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2369 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2370 				"Base port offline: WWN = %s\n", pwwn_buf);
2371 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2372 		} else {
2373 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2374 				"Base port (WWN = %s) "
2375 				"lost fabric connectivity\n", pwwn_buf);
2376 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2377 		}
2378 		break;
2379 
2380 	case BFA_FCPORT_SM_HWFAIL:
2381 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2382 		bfa_fcport_reset_linkinfo(fcport);
2383 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2384 		wwn2str(pwwn_buf, fcport->pwwn);
2385 		if (BFA_PORT_IS_DISABLED(fcport->bfa)) {
2386 			BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2387 				"Base port offline: WWN = %s\n", pwwn_buf);
2388 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_OFFLINE);
2389 		} else {
2390 			BFA_LOG(KERN_ERR, bfad, bfa_log_level,
2391 				"Base port (WWN = %s) "
2392 				"lost fabric connectivity\n", pwwn_buf);
2393 			bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2394 		}
2395 		break;
2396 
2397 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2398 		bfa_fcport_reset_linkinfo(fcport);
2399 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2400 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2401 		break;
2402 
2403 	default:
2404 		bfa_sm_fault(fcport->bfa, event);
2405 	}
2406 }
2407 
2408 static void
2409 bfa_fcport_sm_disabling_qwait(struct bfa_fcport_s *fcport,
2410 				 enum bfa_fcport_sm_event event)
2411 {
2412 	bfa_trc(fcport->bfa, event);
2413 
2414 	switch (event) {
2415 	case BFA_FCPORT_SM_QRESUME:
2416 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2417 		bfa_fcport_send_disable(fcport);
2418 		break;
2419 
2420 	case BFA_FCPORT_SM_STOP:
2421 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2422 		bfa_reqq_wcancel(&fcport->reqq_wait);
2423 		break;
2424 
2425 	case BFA_FCPORT_SM_ENABLE:
2426 		bfa_sm_set_state(fcport, bfa_fcport_sm_toggling_qwait);
2427 		break;
2428 
2429 	case BFA_FCPORT_SM_DISABLE:
2430 		/*
2431 		 * Already being disabled.
2432 		 */
2433 		break;
2434 
2435 	case BFA_FCPORT_SM_LINKUP:
2436 	case BFA_FCPORT_SM_LINKDOWN:
2437 		/*
2438 		 * Possible to get link events when doing back-to-back
2439 		 * enable/disables.
2440 		 */
2441 		break;
2442 
2443 	case BFA_FCPORT_SM_HWFAIL:
2444 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2445 		bfa_reqq_wcancel(&fcport->reqq_wait);
2446 		break;
2447 
2448 	case BFA_FCPORT_SM_FAA_MISCONFIG:
2449 		bfa_fcport_reset_linkinfo(fcport);
2450 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISCONNECT);
2451 		bfa_sm_set_state(fcport, bfa_fcport_sm_faa_misconfig);
2452 		break;
2453 
2454 	default:
2455 		bfa_sm_fault(fcport->bfa, event);
2456 	}
2457 }
2458 
2459 static void
2460 bfa_fcport_sm_toggling_qwait(struct bfa_fcport_s *fcport,
2461 				 enum bfa_fcport_sm_event event)
2462 {
2463 	bfa_trc(fcport->bfa, event);
2464 
2465 	switch (event) {
2466 	case BFA_FCPORT_SM_QRESUME:
2467 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2468 		bfa_fcport_send_disable(fcport);
2469 		if (bfa_fcport_send_enable(fcport))
2470 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2471 		else
2472 			bfa_sm_set_state(fcport,
2473 					 bfa_fcport_sm_enabling_qwait);
2474 		break;
2475 
2476 	case BFA_FCPORT_SM_STOP:
2477 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2478 		bfa_reqq_wcancel(&fcport->reqq_wait);
2479 		break;
2480 
2481 	case BFA_FCPORT_SM_ENABLE:
2482 		break;
2483 
2484 	case BFA_FCPORT_SM_DISABLE:
2485 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2486 		break;
2487 
2488 	case BFA_FCPORT_SM_LINKUP:
2489 	case BFA_FCPORT_SM_LINKDOWN:
2490 		/*
2491 		 * Possible to get link events when doing back-to-back
2492 		 * enable/disables.
2493 		 */
2494 		break;
2495 
2496 	case BFA_FCPORT_SM_HWFAIL:
2497 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2498 		bfa_reqq_wcancel(&fcport->reqq_wait);
2499 		break;
2500 
2501 	default:
2502 		bfa_sm_fault(fcport->bfa, event);
2503 	}
2504 }
2505 
2506 static void
2507 bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
2508 						enum bfa_fcport_sm_event event)
2509 {
2510 	char pwwn_buf[BFA_STRING_32];
2511 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2512 	bfa_trc(fcport->bfa, event);
2513 
2514 	switch (event) {
2515 	case BFA_FCPORT_SM_FWRSP:
2516 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2517 		break;
2518 
2519 	case BFA_FCPORT_SM_DISABLE:
2520 		/*
2521 		 * Already being disabled.
2522 		 */
2523 		break;
2524 
2525 	case BFA_FCPORT_SM_ENABLE:
2526 		if (bfa_fcport_send_enable(fcport))
2527 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2528 		else
2529 			bfa_sm_set_state(fcport,
2530 					 bfa_fcport_sm_enabling_qwait);
2531 
2532 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2533 				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2534 		wwn2str(pwwn_buf, fcport->pwwn);
2535 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2536 			"Base port enabled: WWN = %s\n", pwwn_buf);
2537 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2538 		break;
2539 
2540 	case BFA_FCPORT_SM_STOP:
2541 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2542 		break;
2543 
2544 	case BFA_FCPORT_SM_LINKUP:
2545 	case BFA_FCPORT_SM_LINKDOWN:
2546 		/*
2547 		 * Possible to get link events when doing back-to-back
2548 		 * enable/disables.
2549 		 */
2550 		break;
2551 
2552 	case BFA_FCPORT_SM_HWFAIL:
2553 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2554 		break;
2555 
2556 	default:
2557 		bfa_sm_fault(fcport->bfa, event);
2558 	}
2559 }
2560 
2561 static void
2562 bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
2563 						enum bfa_fcport_sm_event event)
2564 {
2565 	char pwwn_buf[BFA_STRING_32];
2566 	struct bfad_s *bfad = (struct bfad_s *)fcport->bfa->bfad;
2567 	bfa_trc(fcport->bfa, event);
2568 
2569 	switch (event) {
2570 	case BFA_FCPORT_SM_START:
2571 		/*
2572 		 * Ignore start event for a port that is disabled.
2573 		 */
2574 		break;
2575 
2576 	case BFA_FCPORT_SM_STOP:
2577 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2578 		break;
2579 
2580 	case BFA_FCPORT_SM_ENABLE:
2581 		if (bfa_fcport_send_enable(fcport))
2582 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2583 		else
2584 			bfa_sm_set_state(fcport,
2585 					 bfa_fcport_sm_enabling_qwait);
2586 
2587 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2588 				BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
2589 		wwn2str(pwwn_buf, fcport->pwwn);
2590 		BFA_LOG(KERN_INFO, bfad, bfa_log_level,
2591 			"Base port enabled: WWN = %s\n", pwwn_buf);
2592 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_ENABLE);
2593 		break;
2594 
2595 	case BFA_FCPORT_SM_DISABLE:
2596 		/*
2597 		 * Already disabled.
2598 		 */
2599 		break;
2600 
2601 	case BFA_FCPORT_SM_HWFAIL:
2602 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2603 		break;
2604 
2605 	case BFA_FCPORT_SM_DPORTENABLE:
2606 		bfa_sm_set_state(fcport, bfa_fcport_sm_dport);
2607 		break;
2608 
2609 	case BFA_FCPORT_SM_DDPORTENABLE:
2610 		bfa_sm_set_state(fcport, bfa_fcport_sm_ddport);
2611 		break;
2612 
2613 	default:
2614 		bfa_sm_fault(fcport->bfa, event);
2615 	}
2616 }
2617 
2618 static void
2619 bfa_fcport_sm_stopped(struct bfa_fcport_s *fcport,
2620 			 enum bfa_fcport_sm_event event)
2621 {
2622 	bfa_trc(fcport->bfa, event);
2623 
2624 	switch (event) {
2625 	case BFA_FCPORT_SM_START:
2626 		if (bfa_fcport_send_enable(fcport))
2627 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2628 		else
2629 			bfa_sm_set_state(fcport,
2630 					 bfa_fcport_sm_enabling_qwait);
2631 		break;
2632 
2633 	default:
2634 		/*
2635 		 * Ignore all other events.
2636 		 */
2637 		;
2638 	}
2639 }
2640 
2641 /*
2642  * Port is enabled. IOC is down/failed.
2643  */
2644 static void
2645 bfa_fcport_sm_iocdown(struct bfa_fcport_s *fcport,
2646 			 enum bfa_fcport_sm_event event)
2647 {
2648 	bfa_trc(fcport->bfa, event);
2649 
2650 	switch (event) {
2651 	case BFA_FCPORT_SM_START:
2652 		if (bfa_fcport_send_enable(fcport))
2653 			bfa_sm_set_state(fcport, bfa_fcport_sm_enabling);
2654 		else
2655 			bfa_sm_set_state(fcport,
2656 					 bfa_fcport_sm_enabling_qwait);
2657 		break;
2658 
2659 	default:
2660 		/*
2661 		 * Ignore all events.
2662 		 */
2663 		;
2664 	}
2665 }
2666 
2667 /*
2668  * Port is disabled. IOC is down/failed.
2669  */
2670 static void
2671 bfa_fcport_sm_iocfail(struct bfa_fcport_s *fcport,
2672 			 enum bfa_fcport_sm_event event)
2673 {
2674 	bfa_trc(fcport->bfa, event);
2675 
2676 	switch (event) {
2677 	case BFA_FCPORT_SM_START:
2678 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2679 		break;
2680 
2681 	case BFA_FCPORT_SM_ENABLE:
2682 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2683 		break;
2684 
2685 	default:
2686 		/*
2687 		 * Ignore all events.
2688 		 */
2689 		;
2690 	}
2691 }
2692 
2693 static void
2694 bfa_fcport_sm_dport(struct bfa_fcport_s *fcport, enum bfa_fcport_sm_event event)
2695 {
2696 	bfa_trc(fcport->bfa, event);
2697 
2698 	switch (event) {
2699 	case BFA_FCPORT_SM_DPORTENABLE:
2700 	case BFA_FCPORT_SM_DISABLE:
2701 	case BFA_FCPORT_SM_ENABLE:
2702 	case BFA_FCPORT_SM_START:
2703 		/*
2704 		 * Ignore event for a port that is dport
2705 		 */
2706 		break;
2707 
2708 	case BFA_FCPORT_SM_STOP:
2709 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2710 		break;
2711 
2712 	case BFA_FCPORT_SM_HWFAIL:
2713 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2714 		break;
2715 
2716 	case BFA_FCPORT_SM_DPORTDISABLE:
2717 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2718 		break;
2719 
2720 	default:
2721 		bfa_sm_fault(fcport->bfa, event);
2722 	}
2723 }
2724 
2725 static void
2726 bfa_fcport_sm_ddport(struct bfa_fcport_s *fcport,
2727 			enum bfa_fcport_sm_event event)
2728 {
2729 	bfa_trc(fcport->bfa, event);
2730 
2731 	switch (event) {
2732 	case BFA_FCPORT_SM_DISABLE:
2733 	case BFA_FCPORT_SM_DDPORTDISABLE:
2734 		bfa_sm_set_state(fcport, bfa_fcport_sm_disabled);
2735 		break;
2736 
2737 	case BFA_FCPORT_SM_DPORTENABLE:
2738 	case BFA_FCPORT_SM_DPORTDISABLE:
2739 	case BFA_FCPORT_SM_ENABLE:
2740 	case BFA_FCPORT_SM_START:
2741 		/**
2742 		 * Ignore event for a port that is ddport
2743 		 */
2744 		break;
2745 
2746 	case BFA_FCPORT_SM_STOP:
2747 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2748 		break;
2749 
2750 	case BFA_FCPORT_SM_HWFAIL:
2751 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocfail);
2752 		break;
2753 
2754 	default:
2755 		bfa_sm_fault(fcport->bfa, event);
2756 	}
2757 }
2758 
2759 static void
2760 bfa_fcport_sm_faa_misconfig(struct bfa_fcport_s *fcport,
2761 			    enum bfa_fcport_sm_event event)
2762 {
2763 	bfa_trc(fcport->bfa, event);
2764 
2765 	switch (event) {
2766 	case BFA_FCPORT_SM_DPORTENABLE:
2767 	case BFA_FCPORT_SM_ENABLE:
2768 	case BFA_FCPORT_SM_START:
2769 		/*
2770 		 * Ignore event for a port as there is FAA misconfig
2771 		 */
2772 		break;
2773 
2774 	case BFA_FCPORT_SM_DISABLE:
2775 		if (bfa_fcport_send_disable(fcport))
2776 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling);
2777 		else
2778 			bfa_sm_set_state(fcport, bfa_fcport_sm_disabling_qwait);
2779 
2780 		bfa_fcport_reset_linkinfo(fcport);
2781 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2782 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
2783 			     BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
2784 		bfa_fcport_aen_post(fcport, BFA_PORT_AEN_DISABLE);
2785 		break;
2786 
2787 	case BFA_FCPORT_SM_STOP:
2788 		bfa_sm_set_state(fcport, bfa_fcport_sm_stopped);
2789 		break;
2790 
2791 	case BFA_FCPORT_SM_HWFAIL:
2792 		bfa_fcport_reset_linkinfo(fcport);
2793 		bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
2794 		bfa_sm_set_state(fcport, bfa_fcport_sm_iocdown);
2795 		break;
2796 
2797 	default:
2798 		bfa_sm_fault(fcport->bfa, event);
2799 	}
2800 }
2801 
2802 /*
2803  * Link state is down
2804  */
2805 static void
2806 bfa_fcport_ln_sm_dn(struct bfa_fcport_ln_s *ln,
2807 		enum bfa_fcport_ln_sm_event event)
2808 {
2809 	bfa_trc(ln->fcport->bfa, event);
2810 
2811 	switch (event) {
2812 	case BFA_FCPORT_LN_SM_LINKUP:
2813 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2814 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2815 		break;
2816 
2817 	default:
2818 		bfa_sm_fault(ln->fcport->bfa, event);
2819 	}
2820 }
2821 
2822 /*
2823  * Link state is waiting for down notification
2824  */
2825 static void
2826 bfa_fcport_ln_sm_dn_nf(struct bfa_fcport_ln_s *ln,
2827 		enum bfa_fcport_ln_sm_event event)
2828 {
2829 	bfa_trc(ln->fcport->bfa, event);
2830 
2831 	switch (event) {
2832 	case BFA_FCPORT_LN_SM_LINKUP:
2833 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2834 		break;
2835 
2836 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2837 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
2838 		break;
2839 
2840 	default:
2841 		bfa_sm_fault(ln->fcport->bfa, event);
2842 	}
2843 }
2844 
2845 /*
2846  * Link state is waiting for down notification and there is a pending up
2847  */
2848 static void
2849 bfa_fcport_ln_sm_dn_up_nf(struct bfa_fcport_ln_s *ln,
2850 		enum bfa_fcport_ln_sm_event event)
2851 {
2852 	bfa_trc(ln->fcport->bfa, event);
2853 
2854 	switch (event) {
2855 	case BFA_FCPORT_LN_SM_LINKDOWN:
2856 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2857 		break;
2858 
2859 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2860 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_nf);
2861 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKUP);
2862 		break;
2863 
2864 	default:
2865 		bfa_sm_fault(ln->fcport->bfa, event);
2866 	}
2867 }
2868 
2869 /*
2870  * Link state is up
2871  */
2872 static void
2873 bfa_fcport_ln_sm_up(struct bfa_fcport_ln_s *ln,
2874 		enum bfa_fcport_ln_sm_event event)
2875 {
2876 	bfa_trc(ln->fcport->bfa, event);
2877 
2878 	switch (event) {
2879 	case BFA_FCPORT_LN_SM_LINKDOWN:
2880 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2881 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2882 		break;
2883 
2884 	default:
2885 		bfa_sm_fault(ln->fcport->bfa, event);
2886 	}
2887 }
2888 
2889 /*
2890  * Link state is waiting for up notification
2891  */
2892 static void
2893 bfa_fcport_ln_sm_up_nf(struct bfa_fcport_ln_s *ln,
2894 		enum bfa_fcport_ln_sm_event event)
2895 {
2896 	bfa_trc(ln->fcport->bfa, event);
2897 
2898 	switch (event) {
2899 	case BFA_FCPORT_LN_SM_LINKDOWN:
2900 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2901 		break;
2902 
2903 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2904 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up);
2905 		break;
2906 
2907 	default:
2908 		bfa_sm_fault(ln->fcport->bfa, event);
2909 	}
2910 }
2911 
2912 /*
2913  * Link state is waiting for up notification and there is a pending down
2914  */
2915 static void
2916 bfa_fcport_ln_sm_up_dn_nf(struct bfa_fcport_ln_s *ln,
2917 		enum bfa_fcport_ln_sm_event event)
2918 {
2919 	bfa_trc(ln->fcport->bfa, event);
2920 
2921 	switch (event) {
2922 	case BFA_FCPORT_LN_SM_LINKUP:
2923 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_up_nf);
2924 		break;
2925 
2926 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2927 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_nf);
2928 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2929 		break;
2930 
2931 	default:
2932 		bfa_sm_fault(ln->fcport->bfa, event);
2933 	}
2934 }
2935 
2936 /*
2937  * Link state is waiting for up notification and there are pending down and up
2938  */
2939 static void
2940 bfa_fcport_ln_sm_up_dn_up_nf(struct bfa_fcport_ln_s *ln,
2941 			enum bfa_fcport_ln_sm_event event)
2942 {
2943 	bfa_trc(ln->fcport->bfa, event);
2944 
2945 	switch (event) {
2946 	case BFA_FCPORT_LN_SM_LINKDOWN:
2947 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_up_dn_nf);
2948 		break;
2949 
2950 	case BFA_FCPORT_LN_SM_NOTIFICATION:
2951 		bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn_up_nf);
2952 		bfa_fcport_queue_cb(ln, BFA_PORT_LINKDOWN);
2953 		break;
2954 
2955 	default:
2956 		bfa_sm_fault(ln->fcport->bfa, event);
2957 	}
2958 }
2959 
2960 static void
2961 __bfa_cb_fcport_event(void *cbarg, bfa_boolean_t complete)
2962 {
2963 	struct bfa_fcport_ln_s *ln = cbarg;
2964 
2965 	if (complete)
2966 		ln->fcport->event_cbfn(ln->fcport->event_cbarg, ln->ln_event);
2967 	else
2968 		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
2969 }
2970 
2971 /*
2972  * Send SCN notification to upper layers.
2973  * trunk - false if caller is fcport to ignore fcport event in trunked mode
2974  */
2975 static void
2976 bfa_fcport_scn(struct bfa_fcport_s *fcport, enum bfa_port_linkstate event,
2977 	bfa_boolean_t trunk)
2978 {
2979 	if (fcport->cfg.trunked && !trunk)
2980 		return;
2981 
2982 	switch (event) {
2983 	case BFA_PORT_LINKUP:
2984 		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKUP);
2985 		break;
2986 	case BFA_PORT_LINKDOWN:
2987 		bfa_sm_send_event(&fcport->ln, BFA_FCPORT_LN_SM_LINKDOWN);
2988 		break;
2989 	default:
2990 		WARN_ON(1);
2991 	}
2992 }
2993 
2994 static void
2995 bfa_fcport_queue_cb(struct bfa_fcport_ln_s *ln, enum bfa_port_linkstate event)
2996 {
2997 	struct bfa_fcport_s *fcport = ln->fcport;
2998 
2999 	if (fcport->bfa->fcs) {
3000 		fcport->event_cbfn(fcport->event_cbarg, event);
3001 		bfa_sm_send_event(ln, BFA_FCPORT_LN_SM_NOTIFICATION);
3002 	} else {
3003 		ln->ln_event = event;
3004 		bfa_cb_queue(fcport->bfa, &ln->ln_qe,
3005 			__bfa_cb_fcport_event, ln);
3006 	}
3007 }
3008 
3009 #define FCPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_fcport_stats_u), \
3010 							BFA_CACHELINE_SZ))
3011 
3012 void
3013 bfa_fcport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
3014 		   struct bfa_s *bfa)
3015 {
3016 	struct bfa_mem_dma_s *fcport_dma = BFA_MEM_FCPORT_DMA(bfa);
3017 
3018 	bfa_mem_dma_setup(minfo, fcport_dma, FCPORT_STATS_DMA_SZ);
3019 }
3020 
3021 static void
3022 bfa_fcport_qresume(void *cbarg)
3023 {
3024 	struct bfa_fcport_s *fcport = cbarg;
3025 
3026 	bfa_sm_send_event(fcport, BFA_FCPORT_SM_QRESUME);
3027 }
3028 
3029 static void
3030 bfa_fcport_mem_claim(struct bfa_fcport_s *fcport)
3031 {
3032 	struct bfa_mem_dma_s *fcport_dma = &fcport->fcport_dma;
3033 
3034 	fcport->stats_kva = bfa_mem_dma_virt(fcport_dma);
3035 	fcport->stats_pa  = bfa_mem_dma_phys(fcport_dma);
3036 	fcport->stats = (union bfa_fcport_stats_u *)
3037 				bfa_mem_dma_virt(fcport_dma);
3038 }
3039 
3040 /*
3041  * Memory initialization.
3042  */
3043 void
3044 bfa_fcport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
3045 		struct bfa_pcidev_s *pcidev)
3046 {
3047 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3048 	struct bfa_port_cfg_s *port_cfg = &fcport->cfg;
3049 	struct bfa_fcport_ln_s *ln = &fcport->ln;
3050 	struct timeval tv;
3051 
3052 	fcport->bfa = bfa;
3053 	ln->fcport = fcport;
3054 
3055 	bfa_fcport_mem_claim(fcport);
3056 
3057 	bfa_sm_set_state(fcport, bfa_fcport_sm_uninit);
3058 	bfa_sm_set_state(ln, bfa_fcport_ln_sm_dn);
3059 
3060 	/*
3061 	 * initialize time stamp for stats reset
3062 	 */
3063 	do_gettimeofday(&tv);
3064 	fcport->stats_reset_time = tv.tv_sec;
3065 	fcport->stats_dma_ready = BFA_FALSE;
3066 
3067 	/*
3068 	 * initialize and set default configuration
3069 	 */
3070 	port_cfg->topology = BFA_PORT_TOPOLOGY_P2P;
3071 	port_cfg->speed = BFA_PORT_SPEED_AUTO;
3072 	port_cfg->trunked = BFA_FALSE;
3073 	port_cfg->maxfrsize = 0;
3074 
3075 	port_cfg->trl_def_speed = BFA_PORT_SPEED_1GBPS;
3076 	port_cfg->qos_bw.high = BFA_QOS_BW_HIGH;
3077 	port_cfg->qos_bw.med = BFA_QOS_BW_MED;
3078 	port_cfg->qos_bw.low = BFA_QOS_BW_LOW;
3079 
3080 	fcport->fec_state = BFA_FEC_OFFLINE;
3081 
3082 	INIT_LIST_HEAD(&fcport->stats_pending_q);
3083 	INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3084 
3085 	bfa_reqq_winit(&fcport->reqq_wait, bfa_fcport_qresume, fcport);
3086 }
3087 
3088 void
3089 bfa_fcport_start(struct bfa_s *bfa)
3090 {
3091 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_START);
3092 }
3093 
3094 /*
3095  * Called when IOC failure is detected.
3096  */
3097 void
3098 bfa_fcport_iocdisable(struct bfa_s *bfa)
3099 {
3100 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3101 
3102 	bfa_sm_send_event(fcport, BFA_FCPORT_SM_HWFAIL);
3103 	bfa_trunk_iocdisable(bfa);
3104 }
3105 
3106 /*
3107  * Update loop info in fcport for SCN online
3108  */
3109 static void
3110 bfa_fcport_update_loop_info(struct bfa_fcport_s *fcport,
3111 			struct bfa_fcport_loop_info_s *loop_info)
3112 {
3113 	fcport->myalpa = loop_info->myalpa;
3114 	fcport->alpabm_valid =
3115 			loop_info->alpabm_val;
3116 	memcpy(fcport->alpabm.alpa_bm,
3117 			loop_info->alpabm.alpa_bm,
3118 			sizeof(struct fc_alpabm_s));
3119 }
3120 
3121 static void
3122 bfa_fcport_update_linkinfo(struct bfa_fcport_s *fcport)
3123 {
3124 	struct bfi_fcport_event_s *pevent = fcport->event_arg.i2hmsg.event;
3125 	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3126 
3127 	fcport->speed = pevent->link_state.speed;
3128 	fcport->topology = pevent->link_state.topology;
3129 
3130 	if (fcport->topology == BFA_PORT_TOPOLOGY_LOOP) {
3131 		bfa_fcport_update_loop_info(fcport,
3132 				&pevent->link_state.attr.loop_info);
3133 		return;
3134 	}
3135 
3136 	/* QoS Details */
3137 	fcport->qos_attr = pevent->link_state.qos_attr;
3138 	fcport->qos_vc_attr = pevent->link_state.attr.vc_fcf.qos_vc_attr;
3139 
3140 	if (fcport->cfg.bb_cr_enabled)
3141 		fcport->bbcr_attr = pevent->link_state.attr.bbcr_attr;
3142 
3143 	fcport->fec_state = pevent->link_state.fec_state;
3144 
3145 	/*
3146 	 * update trunk state if applicable
3147 	 */
3148 	if (!fcport->cfg.trunked)
3149 		trunk->attr.state = BFA_TRUNK_DISABLED;
3150 
3151 	/* update FCoE specific */
3152 	fcport->fcoe_vlan =
3153 		be16_to_cpu(pevent->link_state.attr.vc_fcf.fcf.vlan);
3154 
3155 	bfa_trc(fcport->bfa, fcport->speed);
3156 	bfa_trc(fcport->bfa, fcport->topology);
3157 }
3158 
3159 static void
3160 bfa_fcport_reset_linkinfo(struct bfa_fcport_s *fcport)
3161 {
3162 	fcport->speed = BFA_PORT_SPEED_UNKNOWN;
3163 	fcport->topology = BFA_PORT_TOPOLOGY_NONE;
3164 	fcport->fec_state = BFA_FEC_OFFLINE;
3165 }
3166 
3167 /*
3168  * Send port enable message to firmware.
3169  */
3170 static bfa_boolean_t
3171 bfa_fcport_send_enable(struct bfa_fcport_s *fcport)
3172 {
3173 	struct bfi_fcport_enable_req_s *m;
3174 
3175 	/*
3176 	 * Increment message tag before queue check, so that responses to old
3177 	 * requests are discarded.
3178 	 */
3179 	fcport->msgtag++;
3180 
3181 	/*
3182 	 * check for room in queue to send request now
3183 	 */
3184 	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3185 	if (!m) {
3186 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3187 							&fcport->reqq_wait);
3188 		return BFA_FALSE;
3189 	}
3190 
3191 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_ENABLE_REQ,
3192 			bfa_fn_lpu(fcport->bfa));
3193 	m->nwwn = fcport->nwwn;
3194 	m->pwwn = fcport->pwwn;
3195 	m->port_cfg = fcport->cfg;
3196 	m->msgtag = fcport->msgtag;
3197 	m->port_cfg.maxfrsize = cpu_to_be16(fcport->cfg.maxfrsize);
3198 	 m->use_flash_cfg = fcport->use_flash_cfg;
3199 	bfa_dma_be_addr_set(m->stats_dma_addr, fcport->stats_pa);
3200 	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_lo);
3201 	bfa_trc(fcport->bfa, m->stats_dma_addr.a32.addr_hi);
3202 
3203 	/*
3204 	 * queue I/O message to firmware
3205 	 */
3206 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3207 	return BFA_TRUE;
3208 }
3209 
3210 /*
3211  * Send port disable message to firmware.
3212  */
3213 static	bfa_boolean_t
3214 bfa_fcport_send_disable(struct bfa_fcport_s *fcport)
3215 {
3216 	struct bfi_fcport_req_s *m;
3217 
3218 	/*
3219 	 * Increment message tag before queue check, so that responses to old
3220 	 * requests are discarded.
3221 	 */
3222 	fcport->msgtag++;
3223 
3224 	/*
3225 	 * check for room in queue to send request now
3226 	 */
3227 	m = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3228 	if (!m) {
3229 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3230 							&fcport->reqq_wait);
3231 		return BFA_FALSE;
3232 	}
3233 
3234 	bfi_h2i_set(m->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_DISABLE_REQ,
3235 			bfa_fn_lpu(fcport->bfa));
3236 	m->msgtag = fcport->msgtag;
3237 
3238 	/*
3239 	 * queue I/O message to firmware
3240 	 */
3241 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, m->mh);
3242 
3243 	return BFA_TRUE;
3244 }
3245 
3246 static void
3247 bfa_fcport_set_wwns(struct bfa_fcport_s *fcport)
3248 {
3249 	fcport->pwwn = fcport->bfa->ioc.attr->pwwn;
3250 	fcport->nwwn = fcport->bfa->ioc.attr->nwwn;
3251 
3252 	bfa_trc(fcport->bfa, fcport->pwwn);
3253 	bfa_trc(fcport->bfa, fcport->nwwn);
3254 }
3255 
3256 static void
3257 bfa_fcport_qos_stats_swap(struct bfa_qos_stats_s *d,
3258 	struct bfa_qos_stats_s *s)
3259 {
3260 	u32	*dip = (u32 *) d;
3261 	__be32	*sip = (__be32 *) s;
3262 	int		i;
3263 
3264 	/* Now swap the 32 bit fields */
3265 	for (i = 0; i < (sizeof(struct bfa_qos_stats_s)/sizeof(u32)); ++i)
3266 		dip[i] = be32_to_cpu(sip[i]);
3267 }
3268 
3269 static void
3270 bfa_fcport_fcoe_stats_swap(struct bfa_fcoe_stats_s *d,
3271 	struct bfa_fcoe_stats_s *s)
3272 {
3273 	u32	*dip = (u32 *) d;
3274 	__be32	*sip = (__be32 *) s;
3275 	int		i;
3276 
3277 	for (i = 0; i < ((sizeof(struct bfa_fcoe_stats_s))/sizeof(u32));
3278 	     i = i + 2) {
3279 #ifdef __BIG_ENDIAN
3280 		dip[i] = be32_to_cpu(sip[i]);
3281 		dip[i + 1] = be32_to_cpu(sip[i + 1]);
3282 #else
3283 		dip[i] = be32_to_cpu(sip[i + 1]);
3284 		dip[i + 1] = be32_to_cpu(sip[i]);
3285 #endif
3286 	}
3287 }
3288 
3289 static void
3290 __bfa_cb_fcport_stats_get(void *cbarg, bfa_boolean_t complete)
3291 {
3292 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *)cbarg;
3293 	struct bfa_cb_pending_q_s *cb;
3294 	struct list_head *qe, *qen;
3295 	union bfa_fcport_stats_u *ret;
3296 
3297 	if (complete) {
3298 		struct timeval tv;
3299 		if (fcport->stats_status == BFA_STATUS_OK)
3300 			do_gettimeofday(&tv);
3301 
3302 		list_for_each_safe(qe, qen, &fcport->stats_pending_q) {
3303 			bfa_q_deq(&fcport->stats_pending_q, &qe);
3304 			cb = (struct bfa_cb_pending_q_s *)qe;
3305 			if (fcport->stats_status == BFA_STATUS_OK) {
3306 				ret = (union bfa_fcport_stats_u *)cb->data;
3307 				/* Swap FC QoS or FCoE stats */
3308 				if (bfa_ioc_get_fcmode(&fcport->bfa->ioc))
3309 					bfa_fcport_qos_stats_swap(&ret->fcqos,
3310 							&fcport->stats->fcqos);
3311 				else {
3312 					bfa_fcport_fcoe_stats_swap(&ret->fcoe,
3313 							&fcport->stats->fcoe);
3314 					ret->fcoe.secs_reset =
3315 					tv.tv_sec - fcport->stats_reset_time;
3316 				}
3317 			}
3318 			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3319 					fcport->stats_status);
3320 		}
3321 		fcport->stats_status = BFA_STATUS_OK;
3322 	} else {
3323 		INIT_LIST_HEAD(&fcport->stats_pending_q);
3324 		fcport->stats_status = BFA_STATUS_OK;
3325 	}
3326 }
3327 
3328 static void
3329 bfa_fcport_stats_get_timeout(void *cbarg)
3330 {
3331 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3332 
3333 	bfa_trc(fcport->bfa, fcport->stats_qfull);
3334 
3335 	if (fcport->stats_qfull) {
3336 		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3337 		fcport->stats_qfull = BFA_FALSE;
3338 	}
3339 
3340 	fcport->stats_status = BFA_STATUS_ETIMER;
3341 	__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3342 }
3343 
3344 static void
3345 bfa_fcport_send_stats_get(void *cbarg)
3346 {
3347 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3348 	struct bfi_fcport_req_s *msg;
3349 
3350 	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3351 
3352 	if (!msg) {
3353 		fcport->stats_qfull = BFA_TRUE;
3354 		bfa_reqq_winit(&fcport->stats_reqq_wait,
3355 				bfa_fcport_send_stats_get, fcport);
3356 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3357 				&fcport->stats_reqq_wait);
3358 		return;
3359 	}
3360 	fcport->stats_qfull = BFA_FALSE;
3361 
3362 	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3363 	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_GET_REQ,
3364 			bfa_fn_lpu(fcport->bfa));
3365 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3366 }
3367 
3368 static void
3369 __bfa_cb_fcport_stats_clr(void *cbarg, bfa_boolean_t complete)
3370 {
3371 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3372 	struct bfa_cb_pending_q_s *cb;
3373 	struct list_head *qe, *qen;
3374 
3375 	if (complete) {
3376 		struct timeval tv;
3377 
3378 		/*
3379 		 * re-initialize time stamp for stats reset
3380 		 */
3381 		do_gettimeofday(&tv);
3382 		fcport->stats_reset_time = tv.tv_sec;
3383 		list_for_each_safe(qe, qen, &fcport->statsclr_pending_q) {
3384 			bfa_q_deq(&fcport->statsclr_pending_q, &qe);
3385 			cb = (struct bfa_cb_pending_q_s *)qe;
3386 			bfa_cb_queue_status(fcport->bfa, &cb->hcb_qe,
3387 						fcport->stats_status);
3388 		}
3389 		fcport->stats_status = BFA_STATUS_OK;
3390 	} else {
3391 		INIT_LIST_HEAD(&fcport->statsclr_pending_q);
3392 		fcport->stats_status = BFA_STATUS_OK;
3393 	}
3394 }
3395 
3396 static void
3397 bfa_fcport_stats_clr_timeout(void *cbarg)
3398 {
3399 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3400 
3401 	bfa_trc(fcport->bfa, fcport->stats_qfull);
3402 
3403 	if (fcport->stats_qfull) {
3404 		bfa_reqq_wcancel(&fcport->stats_reqq_wait);
3405 		fcport->stats_qfull = BFA_FALSE;
3406 	}
3407 
3408 	fcport->stats_status = BFA_STATUS_ETIMER;
3409 	__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3410 }
3411 
3412 static void
3413 bfa_fcport_send_stats_clear(void *cbarg)
3414 {
3415 	struct bfa_fcport_s *fcport = (struct bfa_fcport_s *) cbarg;
3416 	struct bfi_fcport_req_s *msg;
3417 
3418 	msg = bfa_reqq_next(fcport->bfa, BFA_REQQ_PORT);
3419 
3420 	if (!msg) {
3421 		fcport->stats_qfull = BFA_TRUE;
3422 		bfa_reqq_winit(&fcport->stats_reqq_wait,
3423 				bfa_fcport_send_stats_clear, fcport);
3424 		bfa_reqq_wait(fcport->bfa, BFA_REQQ_PORT,
3425 						&fcport->stats_reqq_wait);
3426 		return;
3427 	}
3428 	fcport->stats_qfull = BFA_FALSE;
3429 
3430 	memset(msg, 0, sizeof(struct bfi_fcport_req_s));
3431 	bfi_h2i_set(msg->mh, BFI_MC_FCPORT, BFI_FCPORT_H2I_STATS_CLEAR_REQ,
3432 			bfa_fn_lpu(fcport->bfa));
3433 	bfa_reqq_produce(fcport->bfa, BFA_REQQ_PORT, msg->mh);
3434 }
3435 
3436 /*
3437  * Handle trunk SCN event from firmware.
3438  */
3439 static void
3440 bfa_trunk_scn(struct bfa_fcport_s *fcport, struct bfi_fcport_trunk_scn_s *scn)
3441 {
3442 	struct bfa_fcport_trunk_s *trunk = &fcport->trunk;
3443 	struct bfi_fcport_trunk_link_s *tlink;
3444 	struct bfa_trunk_link_attr_s *lattr;
3445 	enum bfa_trunk_state state_prev;
3446 	int i;
3447 	int link_bm = 0;
3448 
3449 	bfa_trc(fcport->bfa, fcport->cfg.trunked);
3450 	WARN_ON(scn->trunk_state != BFA_TRUNK_ONLINE &&
3451 		   scn->trunk_state != BFA_TRUNK_OFFLINE);
3452 
3453 	bfa_trc(fcport->bfa, trunk->attr.state);
3454 	bfa_trc(fcport->bfa, scn->trunk_state);
3455 	bfa_trc(fcport->bfa, scn->trunk_speed);
3456 
3457 	/*
3458 	 * Save off new state for trunk attribute query
3459 	 */
3460 	state_prev = trunk->attr.state;
3461 	if (fcport->cfg.trunked && (trunk->attr.state != BFA_TRUNK_DISABLED))
3462 		trunk->attr.state = scn->trunk_state;
3463 	trunk->attr.speed = scn->trunk_speed;
3464 	for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3465 		lattr = &trunk->attr.link_attr[i];
3466 		tlink = &scn->tlink[i];
3467 
3468 		lattr->link_state = tlink->state;
3469 		lattr->trunk_wwn  = tlink->trunk_wwn;
3470 		lattr->fctl	  = tlink->fctl;
3471 		lattr->speed	  = tlink->speed;
3472 		lattr->deskew	  = be32_to_cpu(tlink->deskew);
3473 
3474 		if (tlink->state == BFA_TRUNK_LINK_STATE_UP) {
3475 			fcport->speed	 = tlink->speed;
3476 			fcport->topology = BFA_PORT_TOPOLOGY_P2P;
3477 			link_bm |= 1 << i;
3478 		}
3479 
3480 		bfa_trc(fcport->bfa, lattr->link_state);
3481 		bfa_trc(fcport->bfa, lattr->trunk_wwn);
3482 		bfa_trc(fcport->bfa, lattr->fctl);
3483 		bfa_trc(fcport->bfa, lattr->speed);
3484 		bfa_trc(fcport->bfa, lattr->deskew);
3485 	}
3486 
3487 	switch (link_bm) {
3488 	case 3:
3489 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3490 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,1)");
3491 		break;
3492 	case 2:
3493 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3494 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(-,1)");
3495 		break;
3496 	case 1:
3497 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3498 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk up(0,-)");
3499 		break;
3500 	default:
3501 		bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
3502 			BFA_PL_EID_TRUNK_SCN, 0, "Trunk down");
3503 	}
3504 
3505 	/*
3506 	 * Notify upper layers if trunk state changed.
3507 	 */
3508 	if ((state_prev != trunk->attr.state) ||
3509 		(scn->trunk_state == BFA_TRUNK_OFFLINE)) {
3510 		bfa_fcport_scn(fcport, (scn->trunk_state == BFA_TRUNK_ONLINE) ?
3511 			BFA_PORT_LINKUP : BFA_PORT_LINKDOWN, BFA_TRUE);
3512 	}
3513 }
3514 
3515 static void
3516 bfa_trunk_iocdisable(struct bfa_s *bfa)
3517 {
3518 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3519 	int i = 0;
3520 
3521 	/*
3522 	 * In trunked mode, notify upper layers that link is down
3523 	 */
3524 	if (fcport->cfg.trunked) {
3525 		if (fcport->trunk.attr.state == BFA_TRUNK_ONLINE)
3526 			bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_TRUE);
3527 
3528 		fcport->trunk.attr.state = BFA_TRUNK_OFFLINE;
3529 		fcport->trunk.attr.speed = BFA_PORT_SPEED_UNKNOWN;
3530 		for (i = 0; i < BFA_TRUNK_MAX_PORTS; i++) {
3531 			fcport->trunk.attr.link_attr[i].trunk_wwn = 0;
3532 			fcport->trunk.attr.link_attr[i].fctl =
3533 						BFA_TRUNK_LINK_FCTL_NORMAL;
3534 			fcport->trunk.attr.link_attr[i].link_state =
3535 						BFA_TRUNK_LINK_STATE_DN_LINKDN;
3536 			fcport->trunk.attr.link_attr[i].speed =
3537 						BFA_PORT_SPEED_UNKNOWN;
3538 			fcport->trunk.attr.link_attr[i].deskew = 0;
3539 		}
3540 	}
3541 }
3542 
3543 /*
3544  * Called to initialize port attributes
3545  */
3546 void
3547 bfa_fcport_init(struct bfa_s *bfa)
3548 {
3549 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3550 
3551 	/*
3552 	 * Initialize port attributes from IOC hardware data.
3553 	 */
3554 	bfa_fcport_set_wwns(fcport);
3555 	if (fcport->cfg.maxfrsize == 0)
3556 		fcport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc);
3557 	fcport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc);
3558 	fcport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc);
3559 
3560 	if (bfa_fcport_is_pbcdisabled(bfa))
3561 		bfa->modules.port.pbc_disabled = BFA_TRUE;
3562 
3563 	WARN_ON(!fcport->cfg.maxfrsize);
3564 	WARN_ON(!fcport->cfg.rx_bbcredit);
3565 	WARN_ON(!fcport->speed_sup);
3566 }
3567 
3568 /*
3569  * Firmware message handler.
3570  */
3571 void
3572 bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
3573 {
3574 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3575 	union bfi_fcport_i2h_msg_u i2hmsg;
3576 
3577 	i2hmsg.msg = msg;
3578 	fcport->event_arg.i2hmsg = i2hmsg;
3579 
3580 	bfa_trc(bfa, msg->mhdr.msg_id);
3581 	bfa_trc(bfa, bfa_sm_to_state(hal_port_sm_table, fcport->sm));
3582 
3583 	switch (msg->mhdr.msg_id) {
3584 	case BFI_FCPORT_I2H_ENABLE_RSP:
3585 		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) {
3586 
3587 			fcport->stats_dma_ready = BFA_TRUE;
3588 			if (fcport->use_flash_cfg) {
3589 				fcport->cfg = i2hmsg.penable_rsp->port_cfg;
3590 				fcport->cfg.maxfrsize =
3591 					cpu_to_be16(fcport->cfg.maxfrsize);
3592 				fcport->cfg.path_tov =
3593 					cpu_to_be16(fcport->cfg.path_tov);
3594 				fcport->cfg.q_depth =
3595 					cpu_to_be16(fcport->cfg.q_depth);
3596 
3597 				if (fcport->cfg.trunked)
3598 					fcport->trunk.attr.state =
3599 						BFA_TRUNK_OFFLINE;
3600 				else
3601 					fcport->trunk.attr.state =
3602 						BFA_TRUNK_DISABLED;
3603 				fcport->qos_attr.qos_bw =
3604 					i2hmsg.penable_rsp->port_cfg.qos_bw;
3605 				fcport->use_flash_cfg = BFA_FALSE;
3606 			}
3607 
3608 			if (fcport->cfg.qos_enabled)
3609 				fcport->qos_attr.state = BFA_QOS_OFFLINE;
3610 			else
3611 				fcport->qos_attr.state = BFA_QOS_DISABLED;
3612 
3613 			fcport->qos_attr.qos_bw_op =
3614 					i2hmsg.penable_rsp->port_cfg.qos_bw;
3615 
3616 			if (fcport->cfg.bb_cr_enabled)
3617 				fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3618 			else
3619 				fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3620 
3621 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3622 		}
3623 		break;
3624 
3625 	case BFI_FCPORT_I2H_DISABLE_RSP:
3626 		if (fcport->msgtag == i2hmsg.penable_rsp->msgtag)
3627 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP);
3628 		break;
3629 
3630 	case BFI_FCPORT_I2H_EVENT:
3631 		if (fcport->cfg.bb_cr_enabled)
3632 			fcport->bbcr_attr.state = BFA_BBCR_OFFLINE;
3633 		else
3634 			fcport->bbcr_attr.state = BFA_BBCR_DISABLED;
3635 
3636 		if (i2hmsg.event->link_state.linkstate == BFA_PORT_LINKUP)
3637 			bfa_sm_send_event(fcport, BFA_FCPORT_SM_LINKUP);
3638 		else {
3639 			if (i2hmsg.event->link_state.linkstate_rsn ==
3640 			    BFA_PORT_LINKSTATE_RSN_FAA_MISCONFIG)
3641 				bfa_sm_send_event(fcport,
3642 						  BFA_FCPORT_SM_FAA_MISCONFIG);
3643 			else
3644 				bfa_sm_send_event(fcport,
3645 						  BFA_FCPORT_SM_LINKDOWN);
3646 		}
3647 		fcport->qos_attr.qos_bw_op =
3648 				i2hmsg.event->link_state.qos_attr.qos_bw_op;
3649 		break;
3650 
3651 	case BFI_FCPORT_I2H_TRUNK_SCN:
3652 		bfa_trunk_scn(fcport, i2hmsg.trunk_scn);
3653 		break;
3654 
3655 	case BFI_FCPORT_I2H_STATS_GET_RSP:
3656 		/*
3657 		 * check for timer pop before processing the rsp
3658 		 */
3659 		if (list_empty(&fcport->stats_pending_q) ||
3660 		    (fcport->stats_status == BFA_STATUS_ETIMER))
3661 			break;
3662 
3663 		bfa_timer_stop(&fcport->timer);
3664 		fcport->stats_status = i2hmsg.pstatsget_rsp->status;
3665 		__bfa_cb_fcport_stats_get(fcport, BFA_TRUE);
3666 		break;
3667 
3668 	case BFI_FCPORT_I2H_STATS_CLEAR_RSP:
3669 		/*
3670 		 * check for timer pop before processing the rsp
3671 		 */
3672 		if (list_empty(&fcport->statsclr_pending_q) ||
3673 		    (fcport->stats_status == BFA_STATUS_ETIMER))
3674 			break;
3675 
3676 		bfa_timer_stop(&fcport->timer);
3677 		fcport->stats_status = BFA_STATUS_OK;
3678 		__bfa_cb_fcport_stats_clr(fcport, BFA_TRUE);
3679 		break;
3680 
3681 	case BFI_FCPORT_I2H_ENABLE_AEN:
3682 		bfa_sm_send_event(fcport, BFA_FCPORT_SM_ENABLE);
3683 		break;
3684 
3685 	case BFI_FCPORT_I2H_DISABLE_AEN:
3686 		bfa_sm_send_event(fcport, BFA_FCPORT_SM_DISABLE);
3687 		break;
3688 
3689 	default:
3690 		WARN_ON(1);
3691 	break;
3692 	}
3693 }
3694 
3695 /*
3696  * Registered callback for port events.
3697  */
3698 void
3699 bfa_fcport_event_register(struct bfa_s *bfa,
3700 				void (*cbfn) (void *cbarg,
3701 				enum bfa_port_linkstate event),
3702 				void *cbarg)
3703 {
3704 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3705 
3706 	fcport->event_cbfn = cbfn;
3707 	fcport->event_cbarg = cbarg;
3708 }
3709 
3710 bfa_status_t
3711 bfa_fcport_enable(struct bfa_s *bfa)
3712 {
3713 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3714 
3715 	if (bfa_fcport_is_pbcdisabled(bfa))
3716 		return BFA_STATUS_PBC;
3717 
3718 	if (bfa_ioc_is_disabled(&bfa->ioc))
3719 		return BFA_STATUS_IOC_DISABLED;
3720 
3721 	if (fcport->diag_busy)
3722 		return BFA_STATUS_DIAG_BUSY;
3723 
3724 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_ENABLE);
3725 	return BFA_STATUS_OK;
3726 }
3727 
3728 bfa_status_t
3729 bfa_fcport_disable(struct bfa_s *bfa)
3730 {
3731 	if (bfa_fcport_is_pbcdisabled(bfa))
3732 		return BFA_STATUS_PBC;
3733 
3734 	if (bfa_ioc_is_disabled(&bfa->ioc))
3735 		return BFA_STATUS_IOC_DISABLED;
3736 
3737 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DISABLE);
3738 	return BFA_STATUS_OK;
3739 }
3740 
3741 /* If PBC is disabled on port, return error */
3742 bfa_status_t
3743 bfa_fcport_is_pbcdisabled(struct bfa_s *bfa)
3744 {
3745 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3746 	struct bfa_iocfc_s *iocfc = &bfa->iocfc;
3747 	struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp;
3748 
3749 	if (cfgrsp->pbc_cfg.port_enabled == BFI_PBC_PORT_DISABLED) {
3750 		bfa_trc(bfa, fcport->pwwn);
3751 		return BFA_STATUS_PBC;
3752 	}
3753 	return BFA_STATUS_OK;
3754 }
3755 
3756 /*
3757  * Configure port speed.
3758  */
3759 bfa_status_t
3760 bfa_fcport_cfg_speed(struct bfa_s *bfa, enum bfa_port_speed speed)
3761 {
3762 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3763 
3764 	bfa_trc(bfa, speed);
3765 
3766 	if (fcport->cfg.trunked == BFA_TRUE)
3767 		return BFA_STATUS_TRUNK_ENABLED;
3768 	if ((fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP) &&
3769 			(speed == BFA_PORT_SPEED_16GBPS))
3770 		return BFA_STATUS_UNSUPP_SPEED;
3771 	if ((speed != BFA_PORT_SPEED_AUTO) && (speed > fcport->speed_sup)) {
3772 		bfa_trc(bfa, fcport->speed_sup);
3773 		return BFA_STATUS_UNSUPP_SPEED;
3774 	}
3775 
3776 	/* Port speed entered needs to be checked */
3777 	if (bfa_ioc_get_type(&fcport->bfa->ioc) == BFA_IOC_TYPE_FC) {
3778 		/* For CT2, 1G is not supported */
3779 		if ((speed == BFA_PORT_SPEED_1GBPS) &&
3780 		    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id)))
3781 			return BFA_STATUS_UNSUPP_SPEED;
3782 
3783 		/* Already checked for Auto Speed and Max Speed supp */
3784 		if (!(speed == BFA_PORT_SPEED_1GBPS ||
3785 		      speed == BFA_PORT_SPEED_2GBPS ||
3786 		      speed == BFA_PORT_SPEED_4GBPS ||
3787 		      speed == BFA_PORT_SPEED_8GBPS ||
3788 		      speed == BFA_PORT_SPEED_16GBPS ||
3789 		      speed == BFA_PORT_SPEED_AUTO))
3790 			return BFA_STATUS_UNSUPP_SPEED;
3791 	} else {
3792 		if (speed != BFA_PORT_SPEED_10GBPS)
3793 			return BFA_STATUS_UNSUPP_SPEED;
3794 	}
3795 
3796 	fcport->cfg.speed = speed;
3797 
3798 	return BFA_STATUS_OK;
3799 }
3800 
3801 /*
3802  * Get current speed.
3803  */
3804 enum bfa_port_speed
3805 bfa_fcport_get_speed(struct bfa_s *bfa)
3806 {
3807 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3808 
3809 	return fcport->speed;
3810 }
3811 
3812 /*
3813  * Configure port topology.
3814  */
3815 bfa_status_t
3816 bfa_fcport_cfg_topology(struct bfa_s *bfa, enum bfa_port_topology topology)
3817 {
3818 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3819 
3820 	bfa_trc(bfa, topology);
3821 	bfa_trc(bfa, fcport->cfg.topology);
3822 
3823 	switch (topology) {
3824 	case BFA_PORT_TOPOLOGY_P2P:
3825 		break;
3826 
3827 	case BFA_PORT_TOPOLOGY_LOOP:
3828 		if ((bfa_fcport_is_qos_enabled(bfa) != BFA_FALSE) ||
3829 			(fcport->qos_attr.state != BFA_QOS_DISABLED))
3830 			return BFA_STATUS_ERROR_QOS_ENABLED;
3831 		if (fcport->cfg.ratelimit != BFA_FALSE)
3832 			return BFA_STATUS_ERROR_TRL_ENABLED;
3833 		if ((bfa_fcport_is_trunk_enabled(bfa) != BFA_FALSE) ||
3834 			(fcport->trunk.attr.state != BFA_TRUNK_DISABLED))
3835 			return BFA_STATUS_ERROR_TRUNK_ENABLED;
3836 		if ((bfa_fcport_get_speed(bfa) == BFA_PORT_SPEED_16GBPS) ||
3837 			(fcport->cfg.speed == BFA_PORT_SPEED_16GBPS))
3838 			return BFA_STATUS_UNSUPP_SPEED;
3839 		if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type))
3840 			return BFA_STATUS_LOOP_UNSUPP_MEZZ;
3841 		if (bfa_fcport_is_dport(bfa) != BFA_FALSE)
3842 			return BFA_STATUS_DPORT_ERR;
3843 		if (bfa_fcport_is_ddport(bfa) != BFA_FALSE)
3844 			return BFA_STATUS_DPORT_ERR;
3845 		break;
3846 
3847 	case BFA_PORT_TOPOLOGY_AUTO:
3848 		break;
3849 
3850 	default:
3851 		return BFA_STATUS_EINVAL;
3852 	}
3853 
3854 	fcport->cfg.topology = topology;
3855 	return BFA_STATUS_OK;
3856 }
3857 
3858 /*
3859  * Get current topology.
3860  */
3861 enum bfa_port_topology
3862 bfa_fcport_get_topology(struct bfa_s *bfa)
3863 {
3864 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3865 
3866 	return fcport->topology;
3867 }
3868 
3869 /**
3870  * Get config topology.
3871  */
3872 enum bfa_port_topology
3873 bfa_fcport_get_cfg_topology(struct bfa_s *bfa)
3874 {
3875 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3876 
3877 	return fcport->cfg.topology;
3878 }
3879 
3880 bfa_status_t
3881 bfa_fcport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa)
3882 {
3883 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3884 
3885 	bfa_trc(bfa, alpa);
3886 	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3887 	bfa_trc(bfa, fcport->cfg.hardalpa);
3888 
3889 	fcport->cfg.cfg_hardalpa = BFA_TRUE;
3890 	fcport->cfg.hardalpa = alpa;
3891 
3892 	return BFA_STATUS_OK;
3893 }
3894 
3895 bfa_status_t
3896 bfa_fcport_clr_hardalpa(struct bfa_s *bfa)
3897 {
3898 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3899 
3900 	bfa_trc(bfa, fcport->cfg.cfg_hardalpa);
3901 	bfa_trc(bfa, fcport->cfg.hardalpa);
3902 
3903 	fcport->cfg.cfg_hardalpa = BFA_FALSE;
3904 	return BFA_STATUS_OK;
3905 }
3906 
3907 bfa_boolean_t
3908 bfa_fcport_get_hardalpa(struct bfa_s *bfa, u8 *alpa)
3909 {
3910 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3911 
3912 	*alpa = fcport->cfg.hardalpa;
3913 	return fcport->cfg.cfg_hardalpa;
3914 }
3915 
3916 u8
3917 bfa_fcport_get_myalpa(struct bfa_s *bfa)
3918 {
3919 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3920 
3921 	return fcport->myalpa;
3922 }
3923 
3924 bfa_status_t
3925 bfa_fcport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize)
3926 {
3927 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3928 
3929 	bfa_trc(bfa, maxfrsize);
3930 	bfa_trc(bfa, fcport->cfg.maxfrsize);
3931 
3932 	/* with in range */
3933 	if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ))
3934 		return BFA_STATUS_INVLD_DFSZ;
3935 
3936 	/* power of 2, if not the max frame size of 2112 */
3937 	if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1)))
3938 		return BFA_STATUS_INVLD_DFSZ;
3939 
3940 	fcport->cfg.maxfrsize = maxfrsize;
3941 	return BFA_STATUS_OK;
3942 }
3943 
3944 u16
3945 bfa_fcport_get_maxfrsize(struct bfa_s *bfa)
3946 {
3947 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3948 
3949 	return fcport->cfg.maxfrsize;
3950 }
3951 
3952 u8
3953 bfa_fcport_get_rx_bbcredit(struct bfa_s *bfa)
3954 {
3955 	if (bfa_fcport_get_topology(bfa) != BFA_PORT_TOPOLOGY_LOOP)
3956 		return (BFA_FCPORT_MOD(bfa))->cfg.rx_bbcredit;
3957 
3958 	else
3959 		return 0;
3960 }
3961 
3962 void
3963 bfa_fcport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit)
3964 {
3965 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3966 
3967 	fcport->cfg.tx_bbcredit = (u8)tx_bbcredit;
3968 }
3969 
3970 /*
3971  * Get port attributes.
3972  */
3973 
3974 wwn_t
3975 bfa_fcport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node)
3976 {
3977 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3978 	if (node)
3979 		return fcport->nwwn;
3980 	else
3981 		return fcport->pwwn;
3982 }
3983 
3984 void
3985 bfa_fcport_get_attr(struct bfa_s *bfa, struct bfa_port_attr_s *attr)
3986 {
3987 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
3988 
3989 	memset(attr, 0, sizeof(struct bfa_port_attr_s));
3990 
3991 	attr->nwwn = fcport->nwwn;
3992 	attr->pwwn = fcport->pwwn;
3993 
3994 	attr->factorypwwn =  bfa->ioc.attr->mfg_pwwn;
3995 	attr->factorynwwn =  bfa->ioc.attr->mfg_nwwn;
3996 
3997 	memcpy(&attr->pport_cfg, &fcport->cfg,
3998 		sizeof(struct bfa_port_cfg_s));
3999 	/* speed attributes */
4000 	attr->pport_cfg.speed = fcport->cfg.speed;
4001 	attr->speed_supported = fcport->speed_sup;
4002 	attr->speed = fcport->speed;
4003 	attr->cos_supported = FC_CLASS_3;
4004 
4005 	/* topology attributes */
4006 	attr->pport_cfg.topology = fcport->cfg.topology;
4007 	attr->topology = fcport->topology;
4008 	attr->pport_cfg.trunked = fcport->cfg.trunked;
4009 
4010 	/* beacon attributes */
4011 	attr->beacon = fcport->beacon;
4012 	attr->link_e2e_beacon = fcport->link_e2e_beacon;
4013 
4014 	attr->pport_cfg.path_tov  = bfa_fcpim_path_tov_get(bfa);
4015 	attr->pport_cfg.q_depth  = bfa_fcpim_qdepth_get(bfa);
4016 	attr->port_state = bfa_sm_to_state(hal_port_sm_table, fcport->sm);
4017 
4018 	attr->fec_state = fcport->fec_state;
4019 
4020 	/* PBC Disabled State */
4021 	if (bfa_fcport_is_pbcdisabled(bfa))
4022 		attr->port_state = BFA_PORT_ST_PREBOOT_DISABLED;
4023 	else {
4024 		if (bfa_ioc_is_disabled(&fcport->bfa->ioc))
4025 			attr->port_state = BFA_PORT_ST_IOCDIS;
4026 		else if (bfa_ioc_fw_mismatch(&fcport->bfa->ioc))
4027 			attr->port_state = BFA_PORT_ST_FWMISMATCH;
4028 	}
4029 
4030 	/* FCoE vlan */
4031 	attr->fcoe_vlan = fcport->fcoe_vlan;
4032 }
4033 
4034 #define BFA_FCPORT_STATS_TOV	1000
4035 
4036 /*
4037  * Fetch port statistics (FCQoS or FCoE).
4038  */
4039 bfa_status_t
4040 bfa_fcport_get_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4041 {
4042 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4043 
4044 	if (!bfa_iocfc_is_operational(bfa) ||
4045 	    !fcport->stats_dma_ready)
4046 		return BFA_STATUS_IOC_NON_OP;
4047 
4048 	if (!list_empty(&fcport->statsclr_pending_q))
4049 		return BFA_STATUS_DEVBUSY;
4050 
4051 	if (list_empty(&fcport->stats_pending_q)) {
4052 		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4053 		bfa_fcport_send_stats_get(fcport);
4054 		bfa_timer_start(bfa, &fcport->timer,
4055 				bfa_fcport_stats_get_timeout,
4056 				fcport, BFA_FCPORT_STATS_TOV);
4057 	} else
4058 		list_add_tail(&cb->hcb_qe.qe, &fcport->stats_pending_q);
4059 
4060 	return BFA_STATUS_OK;
4061 }
4062 
4063 /*
4064  * Reset port statistics (FCQoS or FCoE).
4065  */
4066 bfa_status_t
4067 bfa_fcport_clear_stats(struct bfa_s *bfa, struct bfa_cb_pending_q_s *cb)
4068 {
4069 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4070 
4071 	if (!bfa_iocfc_is_operational(bfa) ||
4072 	    !fcport->stats_dma_ready)
4073 		return BFA_STATUS_IOC_NON_OP;
4074 
4075 	if (!list_empty(&fcport->stats_pending_q))
4076 		return BFA_STATUS_DEVBUSY;
4077 
4078 	if (list_empty(&fcport->statsclr_pending_q)) {
4079 		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4080 		bfa_fcport_send_stats_clear(fcport);
4081 		bfa_timer_start(bfa, &fcport->timer,
4082 				bfa_fcport_stats_clr_timeout,
4083 				fcport, BFA_FCPORT_STATS_TOV);
4084 	} else
4085 		list_add_tail(&cb->hcb_qe.qe, &fcport->statsclr_pending_q);
4086 
4087 	return BFA_STATUS_OK;
4088 }
4089 
4090 /*
4091  * Fetch port attributes.
4092  */
4093 bfa_boolean_t
4094 bfa_fcport_is_disabled(struct bfa_s *bfa)
4095 {
4096 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4097 
4098 	return bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4099 		BFA_PORT_ST_DISABLED;
4100 
4101 }
4102 
4103 bfa_boolean_t
4104 bfa_fcport_is_dport(struct bfa_s *bfa)
4105 {
4106 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4107 
4108 	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4109 		BFA_PORT_ST_DPORT);
4110 }
4111 
4112 bfa_boolean_t
4113 bfa_fcport_is_ddport(struct bfa_s *bfa)
4114 {
4115 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4116 
4117 	return (bfa_sm_to_state(hal_port_sm_table, fcport->sm) ==
4118 		BFA_PORT_ST_DDPORT);
4119 }
4120 
4121 bfa_status_t
4122 bfa_fcport_set_qos_bw(struct bfa_s *bfa, struct bfa_qos_bw_s *qos_bw)
4123 {
4124 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4125 	enum bfa_ioc_type_e ioc_type = bfa_get_type(bfa);
4126 
4127 	bfa_trc(bfa, ioc_type);
4128 
4129 	if ((qos_bw->high == 0) || (qos_bw->med == 0) || (qos_bw->low == 0))
4130 		return BFA_STATUS_QOS_BW_INVALID;
4131 
4132 	if ((qos_bw->high + qos_bw->med + qos_bw->low) != 100)
4133 		return BFA_STATUS_QOS_BW_INVALID;
4134 
4135 	if ((qos_bw->med > qos_bw->high) || (qos_bw->low > qos_bw->med) ||
4136 	    (qos_bw->low > qos_bw->high))
4137 		return BFA_STATUS_QOS_BW_INVALID;
4138 
4139 	if ((ioc_type == BFA_IOC_TYPE_FC) &&
4140 	    (fcport->cfg.topology != BFA_PORT_TOPOLOGY_LOOP))
4141 		fcport->cfg.qos_bw = *qos_bw;
4142 
4143 	return BFA_STATUS_OK;
4144 }
4145 
4146 bfa_boolean_t
4147 bfa_fcport_is_ratelim(struct bfa_s *bfa)
4148 {
4149 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4150 
4151 	return fcport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE;
4152 
4153 }
4154 
4155 /*
4156  *	Enable/Disable FAA feature in port config
4157  */
4158 void
4159 bfa_fcport_cfg_faa(struct bfa_s *bfa, u8 state)
4160 {
4161 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4162 
4163 	bfa_trc(bfa, state);
4164 	fcport->cfg.faa_state = state;
4165 }
4166 
4167 /*
4168  * Get default minimum ratelim speed
4169  */
4170 enum bfa_port_speed
4171 bfa_fcport_get_ratelim_speed(struct bfa_s *bfa)
4172 {
4173 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4174 
4175 	bfa_trc(bfa, fcport->cfg.trl_def_speed);
4176 	return fcport->cfg.trl_def_speed;
4177 
4178 }
4179 
4180 void
4181 bfa_fcport_beacon(void *dev, bfa_boolean_t beacon,
4182 		  bfa_boolean_t link_e2e_beacon)
4183 {
4184 	struct bfa_s *bfa = dev;
4185 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4186 
4187 	bfa_trc(bfa, beacon);
4188 	bfa_trc(bfa, link_e2e_beacon);
4189 	bfa_trc(bfa, fcport->beacon);
4190 	bfa_trc(bfa, fcport->link_e2e_beacon);
4191 
4192 	fcport->beacon = beacon;
4193 	fcport->link_e2e_beacon = link_e2e_beacon;
4194 }
4195 
4196 bfa_boolean_t
4197 bfa_fcport_is_linkup(struct bfa_s *bfa)
4198 {
4199 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4200 
4201 	return	(!fcport->cfg.trunked &&
4202 		 bfa_sm_cmp_state(fcport, bfa_fcport_sm_linkup)) ||
4203 		(fcport->cfg.trunked &&
4204 		 fcport->trunk.attr.state == BFA_TRUNK_ONLINE);
4205 }
4206 
4207 bfa_boolean_t
4208 bfa_fcport_is_qos_enabled(struct bfa_s *bfa)
4209 {
4210 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4211 
4212 	return fcport->cfg.qos_enabled;
4213 }
4214 
4215 bfa_boolean_t
4216 bfa_fcport_is_trunk_enabled(struct bfa_s *bfa)
4217 {
4218 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4219 
4220 	return fcport->cfg.trunked;
4221 }
4222 
4223 bfa_status_t
4224 bfa_fcport_cfg_bbcr(struct bfa_s *bfa, bfa_boolean_t on_off, u8 bb_scn)
4225 {
4226 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4227 
4228 	bfa_trc(bfa, on_off);
4229 
4230 	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4231 		return BFA_STATUS_BBCR_FC_ONLY;
4232 
4233 	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type) &&
4234 		(bfa->ioc.attr->card_type != BFA_MFG_TYPE_CHINOOK))
4235 		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
4236 
4237 	if (on_off) {
4238 		if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4239 			return BFA_STATUS_TOPOLOGY_LOOP;
4240 
4241 		if (fcport->cfg.qos_enabled)
4242 			return BFA_STATUS_ERROR_QOS_ENABLED;
4243 
4244 		if (fcport->cfg.trunked)
4245 			return BFA_STATUS_TRUNK_ENABLED;
4246 
4247 		if ((fcport->cfg.speed != BFA_PORT_SPEED_AUTO) &&
4248 			(fcport->cfg.speed < bfa_ioc_speed_sup(&bfa->ioc)))
4249 			return BFA_STATUS_ERR_BBCR_SPEED_UNSUPPORT;
4250 
4251 		if (bfa_ioc_speed_sup(&bfa->ioc) < BFA_PORT_SPEED_8GBPS)
4252 			return BFA_STATUS_FEATURE_NOT_SUPPORTED;
4253 
4254 		if (fcport->cfg.bb_cr_enabled) {
4255 			if (bb_scn != fcport->cfg.bb_scn)
4256 				return BFA_STATUS_BBCR_CFG_NO_CHANGE;
4257 			else
4258 				return BFA_STATUS_NO_CHANGE;
4259 		}
4260 
4261 		if ((bb_scn == 0) || (bb_scn > BFA_BB_SCN_MAX))
4262 			bb_scn = BFA_BB_SCN_DEF;
4263 
4264 		fcport->cfg.bb_cr_enabled = on_off;
4265 		fcport->cfg.bb_scn = bb_scn;
4266 	} else {
4267 		if (!fcport->cfg.bb_cr_enabled)
4268 			return BFA_STATUS_NO_CHANGE;
4269 
4270 		fcport->cfg.bb_cr_enabled = on_off;
4271 		fcport->cfg.bb_scn = 0;
4272 	}
4273 
4274 	return BFA_STATUS_OK;
4275 }
4276 
4277 bfa_status_t
4278 bfa_fcport_get_bbcr_attr(struct bfa_s *bfa,
4279 		struct bfa_bbcr_attr_s *bbcr_attr)
4280 {
4281 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(bfa);
4282 
4283 	if (bfa_ioc_get_type(&fcport->bfa->ioc) != BFA_IOC_TYPE_FC)
4284 		return BFA_STATUS_BBCR_FC_ONLY;
4285 
4286 	if (fcport->cfg.topology == BFA_PORT_TOPOLOGY_LOOP)
4287 		return BFA_STATUS_TOPOLOGY_LOOP;
4288 
4289 	*bbcr_attr = fcport->bbcr_attr;
4290 
4291 	return BFA_STATUS_OK;
4292 }
4293 
4294 void
4295 bfa_fcport_dportenable(struct bfa_s *bfa)
4296 {
4297 	/*
4298 	 * Assume caller check for port is in disable state
4299 	 */
4300 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTENABLE);
4301 	bfa_port_set_dportenabled(&bfa->modules.port, BFA_TRUE);
4302 }
4303 
4304 void
4305 bfa_fcport_dportdisable(struct bfa_s *bfa)
4306 {
4307 	/*
4308 	 * Assume caller check for port is in disable state
4309 	 */
4310 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DPORTDISABLE);
4311 	bfa_port_set_dportenabled(&bfa->modules.port, BFA_FALSE);
4312 }
4313 
4314 void
4315 bfa_fcport_ddportenable(struct bfa_s *bfa)
4316 {
4317 	/*
4318 	 * Assume caller check for port is in disable state
4319 	 */
4320 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTENABLE);
4321 }
4322 
4323 void
4324 bfa_fcport_ddportdisable(struct bfa_s *bfa)
4325 {
4326 	/*
4327 	 * Assume caller check for port is in disable state
4328 	 */
4329 	bfa_sm_send_event(BFA_FCPORT_MOD(bfa), BFA_FCPORT_SM_DDPORTDISABLE);
4330 }
4331 
4332 /*
4333  * Rport State machine functions
4334  */
4335 /*
4336  * Beginning state, only online event expected.
4337  */
4338 static void
4339 bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event)
4340 {
4341 	bfa_trc(rp->bfa, rp->rport_tag);
4342 	bfa_trc(rp->bfa, event);
4343 
4344 	switch (event) {
4345 	case BFA_RPORT_SM_CREATE:
4346 		bfa_stats(rp, sm_un_cr);
4347 		bfa_sm_set_state(rp, bfa_rport_sm_created);
4348 		break;
4349 
4350 	default:
4351 		bfa_stats(rp, sm_un_unexp);
4352 		bfa_sm_fault(rp->bfa, event);
4353 	}
4354 }
4355 
4356 static void
4357 bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event)
4358 {
4359 	bfa_trc(rp->bfa, rp->rport_tag);
4360 	bfa_trc(rp->bfa, event);
4361 
4362 	switch (event) {
4363 	case BFA_RPORT_SM_ONLINE:
4364 		bfa_stats(rp, sm_cr_on);
4365 		if (bfa_rport_send_fwcreate(rp))
4366 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4367 		else
4368 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4369 		break;
4370 
4371 	case BFA_RPORT_SM_DELETE:
4372 		bfa_stats(rp, sm_cr_del);
4373 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4374 		bfa_rport_free(rp);
4375 		break;
4376 
4377 	case BFA_RPORT_SM_HWFAIL:
4378 		bfa_stats(rp, sm_cr_hwf);
4379 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4380 		break;
4381 
4382 	default:
4383 		bfa_stats(rp, sm_cr_unexp);
4384 		bfa_sm_fault(rp->bfa, event);
4385 	}
4386 }
4387 
4388 /*
4389  * Waiting for rport create response from firmware.
4390  */
4391 static void
4392 bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event)
4393 {
4394 	bfa_trc(rp->bfa, rp->rport_tag);
4395 	bfa_trc(rp->bfa, event);
4396 
4397 	switch (event) {
4398 	case BFA_RPORT_SM_FWRSP:
4399 		bfa_stats(rp, sm_fwc_rsp);
4400 		bfa_sm_set_state(rp, bfa_rport_sm_online);
4401 		bfa_rport_online_cb(rp);
4402 		break;
4403 
4404 	case BFA_RPORT_SM_DELETE:
4405 		bfa_stats(rp, sm_fwc_del);
4406 		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4407 		break;
4408 
4409 	case BFA_RPORT_SM_OFFLINE:
4410 		bfa_stats(rp, sm_fwc_off);
4411 		bfa_sm_set_state(rp, bfa_rport_sm_offline_pending);
4412 		break;
4413 
4414 	case BFA_RPORT_SM_HWFAIL:
4415 		bfa_stats(rp, sm_fwc_hwf);
4416 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4417 		break;
4418 
4419 	default:
4420 		bfa_stats(rp, sm_fwc_unexp);
4421 		bfa_sm_fault(rp->bfa, event);
4422 	}
4423 }
4424 
4425 /*
4426  * Request queue is full, awaiting queue resume to send create request.
4427  */
4428 static void
4429 bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4430 {
4431 	bfa_trc(rp->bfa, rp->rport_tag);
4432 	bfa_trc(rp->bfa, event);
4433 
4434 	switch (event) {
4435 	case BFA_RPORT_SM_QRESUME:
4436 		bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4437 		bfa_rport_send_fwcreate(rp);
4438 		break;
4439 
4440 	case BFA_RPORT_SM_DELETE:
4441 		bfa_stats(rp, sm_fwc_del);
4442 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4443 		bfa_reqq_wcancel(&rp->reqq_wait);
4444 		bfa_rport_free(rp);
4445 		break;
4446 
4447 	case BFA_RPORT_SM_OFFLINE:
4448 		bfa_stats(rp, sm_fwc_off);
4449 		bfa_sm_set_state(rp, bfa_rport_sm_offline);
4450 		bfa_reqq_wcancel(&rp->reqq_wait);
4451 		bfa_rport_offline_cb(rp);
4452 		break;
4453 
4454 	case BFA_RPORT_SM_HWFAIL:
4455 		bfa_stats(rp, sm_fwc_hwf);
4456 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4457 		bfa_reqq_wcancel(&rp->reqq_wait);
4458 		break;
4459 
4460 	default:
4461 		bfa_stats(rp, sm_fwc_unexp);
4462 		bfa_sm_fault(rp->bfa, event);
4463 	}
4464 }
4465 
4466 /*
4467  * Online state - normal parking state.
4468  */
4469 static void
4470 bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event)
4471 {
4472 	struct bfi_rport_qos_scn_s *qos_scn;
4473 
4474 	bfa_trc(rp->bfa, rp->rport_tag);
4475 	bfa_trc(rp->bfa, event);
4476 
4477 	switch (event) {
4478 	case BFA_RPORT_SM_OFFLINE:
4479 		bfa_stats(rp, sm_on_off);
4480 		if (bfa_rport_send_fwdelete(rp))
4481 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4482 		else
4483 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4484 		break;
4485 
4486 	case BFA_RPORT_SM_DELETE:
4487 		bfa_stats(rp, sm_on_del);
4488 		if (bfa_rport_send_fwdelete(rp))
4489 			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4490 		else
4491 			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4492 		break;
4493 
4494 	case BFA_RPORT_SM_HWFAIL:
4495 		bfa_stats(rp, sm_on_hwf);
4496 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4497 		break;
4498 
4499 	case BFA_RPORT_SM_SET_SPEED:
4500 		bfa_rport_send_fwspeed(rp);
4501 		break;
4502 
4503 	case BFA_RPORT_SM_QOS_SCN:
4504 		qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg;
4505 		rp->qos_attr = qos_scn->new_qos_attr;
4506 		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id);
4507 		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id);
4508 		bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority);
4509 		bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority);
4510 
4511 		qos_scn->old_qos_attr.qos_flow_id  =
4512 			be32_to_cpu(qos_scn->old_qos_attr.qos_flow_id);
4513 		qos_scn->new_qos_attr.qos_flow_id  =
4514 			be32_to_cpu(qos_scn->new_qos_attr.qos_flow_id);
4515 
4516 		if (qos_scn->old_qos_attr.qos_flow_id !=
4517 			qos_scn->new_qos_attr.qos_flow_id)
4518 			bfa_cb_rport_qos_scn_flowid(rp->rport_drv,
4519 						    qos_scn->old_qos_attr,
4520 						    qos_scn->new_qos_attr);
4521 		if (qos_scn->old_qos_attr.qos_priority !=
4522 			qos_scn->new_qos_attr.qos_priority)
4523 			bfa_cb_rport_qos_scn_prio(rp->rport_drv,
4524 						  qos_scn->old_qos_attr,
4525 						  qos_scn->new_qos_attr);
4526 		break;
4527 
4528 	default:
4529 		bfa_stats(rp, sm_on_unexp);
4530 		bfa_sm_fault(rp->bfa, event);
4531 	}
4532 }
4533 
4534 /*
4535  * Firmware rport is being deleted - awaiting f/w response.
4536  */
4537 static void
4538 bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event)
4539 {
4540 	bfa_trc(rp->bfa, rp->rport_tag);
4541 	bfa_trc(rp->bfa, event);
4542 
4543 	switch (event) {
4544 	case BFA_RPORT_SM_FWRSP:
4545 		bfa_stats(rp, sm_fwd_rsp);
4546 		bfa_sm_set_state(rp, bfa_rport_sm_offline);
4547 		bfa_rport_offline_cb(rp);
4548 		break;
4549 
4550 	case BFA_RPORT_SM_DELETE:
4551 		bfa_stats(rp, sm_fwd_del);
4552 		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4553 		break;
4554 
4555 	case BFA_RPORT_SM_HWFAIL:
4556 		bfa_stats(rp, sm_fwd_hwf);
4557 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4558 		bfa_rport_offline_cb(rp);
4559 		break;
4560 
4561 	default:
4562 		bfa_stats(rp, sm_fwd_unexp);
4563 		bfa_sm_fault(rp->bfa, event);
4564 	}
4565 }
4566 
4567 static void
4568 bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4569 {
4570 	bfa_trc(rp->bfa, rp->rport_tag);
4571 	bfa_trc(rp->bfa, event);
4572 
4573 	switch (event) {
4574 	case BFA_RPORT_SM_QRESUME:
4575 		bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4576 		bfa_rport_send_fwdelete(rp);
4577 		break;
4578 
4579 	case BFA_RPORT_SM_DELETE:
4580 		bfa_stats(rp, sm_fwd_del);
4581 		bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4582 		break;
4583 
4584 	case BFA_RPORT_SM_HWFAIL:
4585 		bfa_stats(rp, sm_fwd_hwf);
4586 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4587 		bfa_reqq_wcancel(&rp->reqq_wait);
4588 		bfa_rport_offline_cb(rp);
4589 		break;
4590 
4591 	default:
4592 		bfa_stats(rp, sm_fwd_unexp);
4593 		bfa_sm_fault(rp->bfa, event);
4594 	}
4595 }
4596 
4597 /*
4598  * Offline state.
4599  */
4600 static void
4601 bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event)
4602 {
4603 	bfa_trc(rp->bfa, rp->rport_tag);
4604 	bfa_trc(rp->bfa, event);
4605 
4606 	switch (event) {
4607 	case BFA_RPORT_SM_DELETE:
4608 		bfa_stats(rp, sm_off_del);
4609 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4610 		bfa_rport_free(rp);
4611 		break;
4612 
4613 	case BFA_RPORT_SM_ONLINE:
4614 		bfa_stats(rp, sm_off_on);
4615 		if (bfa_rport_send_fwcreate(rp))
4616 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4617 		else
4618 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4619 		break;
4620 
4621 	case BFA_RPORT_SM_HWFAIL:
4622 		bfa_stats(rp, sm_off_hwf);
4623 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4624 		break;
4625 
4626 	case BFA_RPORT_SM_OFFLINE:
4627 		bfa_rport_offline_cb(rp);
4628 		break;
4629 
4630 	default:
4631 		bfa_stats(rp, sm_off_unexp);
4632 		bfa_sm_fault(rp->bfa, event);
4633 	}
4634 }
4635 
4636 /*
4637  * Rport is deleted, waiting for firmware response to delete.
4638  */
4639 static void
4640 bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event)
4641 {
4642 	bfa_trc(rp->bfa, rp->rport_tag);
4643 	bfa_trc(rp->bfa, event);
4644 
4645 	switch (event) {
4646 	case BFA_RPORT_SM_FWRSP:
4647 		bfa_stats(rp, sm_del_fwrsp);
4648 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4649 		bfa_rport_free(rp);
4650 		break;
4651 
4652 	case BFA_RPORT_SM_HWFAIL:
4653 		bfa_stats(rp, sm_del_hwf);
4654 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4655 		bfa_rport_free(rp);
4656 		break;
4657 
4658 	default:
4659 		bfa_sm_fault(rp->bfa, event);
4660 	}
4661 }
4662 
4663 static void
4664 bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event)
4665 {
4666 	bfa_trc(rp->bfa, rp->rport_tag);
4667 	bfa_trc(rp->bfa, event);
4668 
4669 	switch (event) {
4670 	case BFA_RPORT_SM_QRESUME:
4671 		bfa_stats(rp, sm_del_fwrsp);
4672 		bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4673 		bfa_rport_send_fwdelete(rp);
4674 		break;
4675 
4676 	case BFA_RPORT_SM_HWFAIL:
4677 		bfa_stats(rp, sm_del_hwf);
4678 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4679 		bfa_reqq_wcancel(&rp->reqq_wait);
4680 		bfa_rport_free(rp);
4681 		break;
4682 
4683 	default:
4684 		bfa_sm_fault(rp->bfa, event);
4685 	}
4686 }
4687 
4688 /*
4689  * Waiting for rport create response from firmware. A delete is pending.
4690  */
4691 static void
4692 bfa_rport_sm_delete_pending(struct bfa_rport_s *rp,
4693 				enum bfa_rport_event event)
4694 {
4695 	bfa_trc(rp->bfa, rp->rport_tag);
4696 	bfa_trc(rp->bfa, event);
4697 
4698 	switch (event) {
4699 	case BFA_RPORT_SM_FWRSP:
4700 		bfa_stats(rp, sm_delp_fwrsp);
4701 		if (bfa_rport_send_fwdelete(rp))
4702 			bfa_sm_set_state(rp, bfa_rport_sm_deleting);
4703 		else
4704 			bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull);
4705 		break;
4706 
4707 	case BFA_RPORT_SM_HWFAIL:
4708 		bfa_stats(rp, sm_delp_hwf);
4709 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4710 		bfa_rport_free(rp);
4711 		break;
4712 
4713 	default:
4714 		bfa_stats(rp, sm_delp_unexp);
4715 		bfa_sm_fault(rp->bfa, event);
4716 	}
4717 }
4718 
4719 /*
4720  * Waiting for rport create response from firmware. Rport offline is pending.
4721  */
4722 static void
4723 bfa_rport_sm_offline_pending(struct bfa_rport_s *rp,
4724 				 enum bfa_rport_event event)
4725 {
4726 	bfa_trc(rp->bfa, rp->rport_tag);
4727 	bfa_trc(rp->bfa, event);
4728 
4729 	switch (event) {
4730 	case BFA_RPORT_SM_FWRSP:
4731 		bfa_stats(rp, sm_offp_fwrsp);
4732 		if (bfa_rport_send_fwdelete(rp))
4733 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete);
4734 		else
4735 			bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull);
4736 		break;
4737 
4738 	case BFA_RPORT_SM_DELETE:
4739 		bfa_stats(rp, sm_offp_del);
4740 		bfa_sm_set_state(rp, bfa_rport_sm_delete_pending);
4741 		break;
4742 
4743 	case BFA_RPORT_SM_HWFAIL:
4744 		bfa_stats(rp, sm_offp_hwf);
4745 		bfa_sm_set_state(rp, bfa_rport_sm_iocdisable);
4746 		bfa_rport_offline_cb(rp);
4747 		break;
4748 
4749 	default:
4750 		bfa_stats(rp, sm_offp_unexp);
4751 		bfa_sm_fault(rp->bfa, event);
4752 	}
4753 }
4754 
4755 /*
4756  * IOC h/w failed.
4757  */
4758 static void
4759 bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event)
4760 {
4761 	bfa_trc(rp->bfa, rp->rport_tag);
4762 	bfa_trc(rp->bfa, event);
4763 
4764 	switch (event) {
4765 	case BFA_RPORT_SM_OFFLINE:
4766 		bfa_stats(rp, sm_iocd_off);
4767 		bfa_rport_offline_cb(rp);
4768 		break;
4769 
4770 	case BFA_RPORT_SM_DELETE:
4771 		bfa_stats(rp, sm_iocd_del);
4772 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4773 		bfa_rport_free(rp);
4774 		break;
4775 
4776 	case BFA_RPORT_SM_ONLINE:
4777 		bfa_stats(rp, sm_iocd_on);
4778 		if (bfa_rport_send_fwcreate(rp))
4779 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate);
4780 		else
4781 			bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull);
4782 		break;
4783 
4784 	case BFA_RPORT_SM_HWFAIL:
4785 		break;
4786 
4787 	default:
4788 		bfa_stats(rp, sm_iocd_unexp);
4789 		bfa_sm_fault(rp->bfa, event);
4790 	}
4791 }
4792 
4793 
4794 
4795 /*
4796  *  bfa_rport_private BFA rport private functions
4797  */
4798 
4799 static void
4800 __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete)
4801 {
4802 	struct bfa_rport_s *rp = cbarg;
4803 
4804 	if (complete)
4805 		bfa_cb_rport_online(rp->rport_drv);
4806 }
4807 
4808 static void
4809 __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete)
4810 {
4811 	struct bfa_rport_s *rp = cbarg;
4812 
4813 	if (complete)
4814 		bfa_cb_rport_offline(rp->rport_drv);
4815 }
4816 
4817 static void
4818 bfa_rport_qresume(void *cbarg)
4819 {
4820 	struct bfa_rport_s	*rp = cbarg;
4821 
4822 	bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME);
4823 }
4824 
4825 void
4826 bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
4827 		struct bfa_s *bfa)
4828 {
4829 	struct bfa_mem_kva_s *rport_kva = BFA_MEM_RPORT_KVA(bfa);
4830 
4831 	if (cfg->fwcfg.num_rports < BFA_RPORT_MIN)
4832 		cfg->fwcfg.num_rports = BFA_RPORT_MIN;
4833 
4834 	/* kva memory */
4835 	bfa_mem_kva_setup(minfo, rport_kva,
4836 		cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s));
4837 }
4838 
4839 void
4840 bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
4841 		struct bfa_pcidev_s *pcidev)
4842 {
4843 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4844 	struct bfa_rport_s *rp;
4845 	u16 i;
4846 
4847 	INIT_LIST_HEAD(&mod->rp_free_q);
4848 	INIT_LIST_HEAD(&mod->rp_active_q);
4849 	INIT_LIST_HEAD(&mod->rp_unused_q);
4850 
4851 	rp = (struct bfa_rport_s *) bfa_mem_kva_curp(mod);
4852 	mod->rps_list = rp;
4853 	mod->num_rports = cfg->fwcfg.num_rports;
4854 
4855 	WARN_ON(!mod->num_rports ||
4856 		   (mod->num_rports & (mod->num_rports - 1)));
4857 
4858 	for (i = 0; i < mod->num_rports; i++, rp++) {
4859 		memset(rp, 0, sizeof(struct bfa_rport_s));
4860 		rp->bfa = bfa;
4861 		rp->rport_tag = i;
4862 		bfa_sm_set_state(rp, bfa_rport_sm_uninit);
4863 
4864 		/*
4865 		 *  - is unused
4866 		 */
4867 		if (i)
4868 			list_add_tail(&rp->qe, &mod->rp_free_q);
4869 
4870 		bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp);
4871 	}
4872 
4873 	/*
4874 	 * consume memory
4875 	 */
4876 	bfa_mem_kva_curp(mod) = (u8 *) rp;
4877 }
4878 
4879 void
4880 bfa_rport_iocdisable(struct bfa_s *bfa)
4881 {
4882 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa);
4883 	struct bfa_rport_s *rport;
4884 	struct list_head *qe, *qen;
4885 
4886 	/* Enqueue unused rport resources to free_q */
4887 	list_splice_tail_init(&mod->rp_unused_q, &mod->rp_free_q);
4888 
4889 	list_for_each_safe(qe, qen, &mod->rp_active_q) {
4890 		rport = (struct bfa_rport_s *) qe;
4891 		bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL);
4892 	}
4893 }
4894 
4895 static struct bfa_rport_s *
4896 bfa_rport_alloc(struct bfa_rport_mod_s *mod)
4897 {
4898 	struct bfa_rport_s *rport;
4899 
4900 	bfa_q_deq(&mod->rp_free_q, &rport);
4901 	if (rport)
4902 		list_add_tail(&rport->qe, &mod->rp_active_q);
4903 
4904 	return rport;
4905 }
4906 
4907 static void
4908 bfa_rport_free(struct bfa_rport_s *rport)
4909 {
4910 	struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa);
4911 
4912 	WARN_ON(!bfa_q_is_on_q(&mod->rp_active_q, rport));
4913 	list_del(&rport->qe);
4914 	list_add_tail(&rport->qe, &mod->rp_free_q);
4915 }
4916 
4917 static bfa_boolean_t
4918 bfa_rport_send_fwcreate(struct bfa_rport_s *rp)
4919 {
4920 	struct bfi_rport_create_req_s *m;
4921 
4922 	/*
4923 	 * check for room in queue to send request now
4924 	 */
4925 	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4926 	if (!m) {
4927 		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4928 		return BFA_FALSE;
4929 	}
4930 
4931 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ,
4932 			bfa_fn_lpu(rp->bfa));
4933 	m->bfa_handle = rp->rport_tag;
4934 	m->max_frmsz = cpu_to_be16(rp->rport_info.max_frmsz);
4935 	m->pid = rp->rport_info.pid;
4936 	m->lp_fwtag = bfa_lps_get_fwtag(rp->bfa, (u8)rp->rport_info.lp_tag);
4937 	m->local_pid = rp->rport_info.local_pid;
4938 	m->fc_class = rp->rport_info.fc_class;
4939 	m->vf_en = rp->rport_info.vf_en;
4940 	m->vf_id = rp->rport_info.vf_id;
4941 	m->cisc = rp->rport_info.cisc;
4942 
4943 	/*
4944 	 * queue I/O message to firmware
4945 	 */
4946 	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4947 	return BFA_TRUE;
4948 }
4949 
4950 static bfa_boolean_t
4951 bfa_rport_send_fwdelete(struct bfa_rport_s *rp)
4952 {
4953 	struct bfi_rport_delete_req_s *m;
4954 
4955 	/*
4956 	 * check for room in queue to send request now
4957 	 */
4958 	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4959 	if (!m) {
4960 		bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait);
4961 		return BFA_FALSE;
4962 	}
4963 
4964 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ,
4965 			bfa_fn_lpu(rp->bfa));
4966 	m->fw_handle = rp->fw_handle;
4967 
4968 	/*
4969 	 * queue I/O message to firmware
4970 	 */
4971 	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4972 	return BFA_TRUE;
4973 }
4974 
4975 static bfa_boolean_t
4976 bfa_rport_send_fwspeed(struct bfa_rport_s *rp)
4977 {
4978 	struct bfa_rport_speed_req_s *m;
4979 
4980 	/*
4981 	 * check for room in queue to send request now
4982 	 */
4983 	m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT);
4984 	if (!m) {
4985 		bfa_trc(rp->bfa, rp->rport_info.speed);
4986 		return BFA_FALSE;
4987 	}
4988 
4989 	bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ,
4990 			bfa_fn_lpu(rp->bfa));
4991 	m->fw_handle = rp->fw_handle;
4992 	m->speed = (u8)rp->rport_info.speed;
4993 
4994 	/*
4995 	 * queue I/O message to firmware
4996 	 */
4997 	bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT, m->mh);
4998 	return BFA_TRUE;
4999 }
5000 
5001 
5002 
5003 /*
5004  *  bfa_rport_public
5005  */
5006 
5007 /*
5008  * Rport interrupt processing.
5009  */
5010 void
5011 bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m)
5012 {
5013 	union bfi_rport_i2h_msg_u msg;
5014 	struct bfa_rport_s *rp;
5015 
5016 	bfa_trc(bfa, m->mhdr.msg_id);
5017 
5018 	msg.msg = m;
5019 
5020 	switch (m->mhdr.msg_id) {
5021 	case BFI_RPORT_I2H_CREATE_RSP:
5022 		rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle);
5023 		rp->fw_handle = msg.create_rsp->fw_handle;
5024 		rp->qos_attr = msg.create_rsp->qos_attr;
5025 		bfa_rport_set_lunmask(bfa, rp);
5026 		WARN_ON(msg.create_rsp->status != BFA_STATUS_OK);
5027 		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5028 		break;
5029 
5030 	case BFI_RPORT_I2H_DELETE_RSP:
5031 		rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle);
5032 		WARN_ON(msg.delete_rsp->status != BFA_STATUS_OK);
5033 		bfa_rport_unset_lunmask(bfa, rp);
5034 		bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP);
5035 		break;
5036 
5037 	case BFI_RPORT_I2H_QOS_SCN:
5038 		rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle);
5039 		rp->event_arg.fw_msg = msg.qos_scn_evt;
5040 		bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN);
5041 		break;
5042 
5043 	case BFI_RPORT_I2H_LIP_SCN_ONLINE:
5044 		bfa_fcport_update_loop_info(BFA_FCPORT_MOD(bfa),
5045 				&msg.lip_scn->loop_info);
5046 		bfa_cb_rport_scn_online(bfa);
5047 		break;
5048 
5049 	case BFI_RPORT_I2H_LIP_SCN_OFFLINE:
5050 		bfa_cb_rport_scn_offline(bfa);
5051 		break;
5052 
5053 	case BFI_RPORT_I2H_NO_DEV:
5054 		rp = BFA_RPORT_FROM_TAG(bfa, msg.lip_scn->bfa_handle);
5055 		bfa_cb_rport_scn_no_dev(rp->rport_drv);
5056 		break;
5057 
5058 	default:
5059 		bfa_trc(bfa, m->mhdr.msg_id);
5060 		WARN_ON(1);
5061 	}
5062 }
5063 
5064 void
5065 bfa_rport_res_recfg(struct bfa_s *bfa, u16 num_rport_fw)
5066 {
5067 	struct bfa_rport_mod_s	*mod = BFA_RPORT_MOD(bfa);
5068 	struct list_head	*qe;
5069 	int	i;
5070 
5071 	for (i = 0; i < (mod->num_rports - num_rport_fw); i++) {
5072 		bfa_q_deq_tail(&mod->rp_free_q, &qe);
5073 		list_add_tail(qe, &mod->rp_unused_q);
5074 	}
5075 }
5076 
5077 /*
5078  *  bfa_rport_api
5079  */
5080 
5081 struct bfa_rport_s *
5082 bfa_rport_create(struct bfa_s *bfa, void *rport_drv)
5083 {
5084 	struct bfa_rport_s *rp;
5085 
5086 	rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa));
5087 
5088 	if (rp == NULL)
5089 		return NULL;
5090 
5091 	rp->bfa = bfa;
5092 	rp->rport_drv = rport_drv;
5093 	memset(&rp->stats, 0, sizeof(rp->stats));
5094 
5095 	WARN_ON(!bfa_sm_cmp_state(rp, bfa_rport_sm_uninit));
5096 	bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE);
5097 
5098 	return rp;
5099 }
5100 
5101 void
5102 bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info)
5103 {
5104 	WARN_ON(rport_info->max_frmsz == 0);
5105 
5106 	/*
5107 	 * Some JBODs are seen to be not setting PDU size correctly in PLOGI
5108 	 * responses. Default to minimum size.
5109 	 */
5110 	if (rport_info->max_frmsz == 0) {
5111 		bfa_trc(rport->bfa, rport->rport_tag);
5112 		rport_info->max_frmsz = FC_MIN_PDUSZ;
5113 	}
5114 
5115 	rport->rport_info = *rport_info;
5116 	bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE);
5117 }
5118 
5119 void
5120 bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_port_speed speed)
5121 {
5122 	WARN_ON(speed == 0);
5123 	WARN_ON(speed == BFA_PORT_SPEED_AUTO);
5124 
5125 	if (rport) {
5126 		rport->rport_info.speed = speed;
5127 		bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED);
5128 	}
5129 }
5130 
5131 /* Set Rport LUN Mask */
5132 void
5133 bfa_rport_set_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5134 {
5135 	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);
5136 	wwn_t	lp_wwn, rp_wwn;
5137 	u8 lp_tag = (u8)rp->rport_info.lp_tag;
5138 
5139 	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5140 	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5141 
5142 	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5143 					rp->lun_mask = BFA_TRUE;
5144 	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn, rp->rport_tag, lp_tag);
5145 }
5146 
5147 /* Unset Rport LUN mask */
5148 void
5149 bfa_rport_unset_lunmask(struct bfa_s *bfa, struct bfa_rport_s *rp)
5150 {
5151 	struct bfa_lps_mod_s	*lps_mod = BFA_LPS_MOD(bfa);
5152 	wwn_t	lp_wwn, rp_wwn;
5153 
5154 	rp_wwn = ((struct bfa_fcs_rport_s *)rp->rport_drv)->pwwn;
5155 	lp_wwn = (BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag))->pwwn;
5156 
5157 	BFA_LPS_FROM_TAG(lps_mod, rp->rport_info.lp_tag)->lun_mask =
5158 				rp->lun_mask = BFA_FALSE;
5159 	bfa_fcpim_lunmask_rp_update(bfa, lp_wwn, rp_wwn,
5160 			BFA_RPORT_TAG_INVALID, BFA_LP_TAG_INVALID);
5161 }
5162 
5163 /*
5164  * SGPG related functions
5165  */
5166 
5167 /*
5168  * Compute and return memory needed by FCP(im) module.
5169  */
5170 void
5171 bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5172 		struct bfa_s *bfa)
5173 {
5174 	struct bfa_sgpg_mod_s *sgpg_mod = BFA_SGPG_MOD(bfa);
5175 	struct bfa_mem_kva_s *sgpg_kva = BFA_MEM_SGPG_KVA(bfa);
5176 	struct bfa_mem_dma_s *seg_ptr;
5177 	u16	nsegs, idx, per_seg_sgpg, num_sgpg;
5178 	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
5179 
5180 	if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN)
5181 		cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN;
5182 	else if (cfg->drvcfg.num_sgpgs > BFA_SGPG_MAX)
5183 		cfg->drvcfg.num_sgpgs = BFA_SGPG_MAX;
5184 
5185 	num_sgpg = cfg->drvcfg.num_sgpgs;
5186 
5187 	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5188 	per_seg_sgpg = BFI_MEM_NREQS_SEG(sgpg_sz);
5189 
5190 	bfa_mem_dma_seg_iter(sgpg_mod, seg_ptr, nsegs, idx) {
5191 		if (num_sgpg >= per_seg_sgpg) {
5192 			num_sgpg -= per_seg_sgpg;
5193 			bfa_mem_dma_setup(minfo, seg_ptr,
5194 					per_seg_sgpg * sgpg_sz);
5195 		} else
5196 			bfa_mem_dma_setup(minfo, seg_ptr,
5197 					num_sgpg * sgpg_sz);
5198 	}
5199 
5200 	/* kva memory */
5201 	bfa_mem_kva_setup(minfo, sgpg_kva,
5202 		cfg->drvcfg.num_sgpgs * sizeof(struct bfa_sgpg_s));
5203 }
5204 
5205 void
5206 bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5207 		struct bfa_pcidev_s *pcidev)
5208 {
5209 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5210 	struct bfa_sgpg_s *hsgpg;
5211 	struct bfi_sgpg_s *sgpg;
5212 	u64 align_len;
5213 	struct bfa_mem_dma_s *seg_ptr;
5214 	u32	sgpg_sz = sizeof(struct bfi_sgpg_s);
5215 	u16	i, idx, nsegs, per_seg_sgpg, num_sgpg;
5216 
5217 	union {
5218 		u64 pa;
5219 		union bfi_addr_u addr;
5220 	} sgpg_pa, sgpg_pa_tmp;
5221 
5222 	INIT_LIST_HEAD(&mod->sgpg_q);
5223 	INIT_LIST_HEAD(&mod->sgpg_wait_q);
5224 
5225 	bfa_trc(bfa, cfg->drvcfg.num_sgpgs);
5226 
5227 	mod->free_sgpgs = mod->num_sgpgs = cfg->drvcfg.num_sgpgs;
5228 
5229 	num_sgpg = cfg->drvcfg.num_sgpgs;
5230 	nsegs = BFI_MEM_DMA_NSEGS(num_sgpg, sgpg_sz);
5231 
5232 	/* dma/kva mem claim */
5233 	hsgpg = (struct bfa_sgpg_s *) bfa_mem_kva_curp(mod);
5234 
5235 	bfa_mem_dma_seg_iter(mod, seg_ptr, nsegs, idx) {
5236 
5237 		if (!bfa_mem_dma_virt(seg_ptr))
5238 			break;
5239 
5240 		align_len = BFA_SGPG_ROUNDUP(bfa_mem_dma_phys(seg_ptr)) -
5241 					     bfa_mem_dma_phys(seg_ptr);
5242 
5243 		sgpg = (struct bfi_sgpg_s *)
5244 			(((u8 *) bfa_mem_dma_virt(seg_ptr)) + align_len);
5245 		sgpg_pa.pa = bfa_mem_dma_phys(seg_ptr) + align_len;
5246 		WARN_ON(sgpg_pa.pa & (sgpg_sz - 1));
5247 
5248 		per_seg_sgpg = (seg_ptr->mem_len - (u32)align_len) / sgpg_sz;
5249 
5250 		for (i = 0; num_sgpg > 0 && i < per_seg_sgpg; i++, num_sgpg--) {
5251 			memset(hsgpg, 0, sizeof(*hsgpg));
5252 			memset(sgpg, 0, sizeof(*sgpg));
5253 
5254 			hsgpg->sgpg = sgpg;
5255 			sgpg_pa_tmp.pa = bfa_sgaddr_le(sgpg_pa.pa);
5256 			hsgpg->sgpg_pa = sgpg_pa_tmp.addr;
5257 			list_add_tail(&hsgpg->qe, &mod->sgpg_q);
5258 
5259 			sgpg++;
5260 			hsgpg++;
5261 			sgpg_pa.pa += sgpg_sz;
5262 		}
5263 	}
5264 
5265 	bfa_mem_kva_curp(mod) = (u8 *) hsgpg;
5266 }
5267 
5268 bfa_status_t
5269 bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs)
5270 {
5271 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5272 	struct bfa_sgpg_s *hsgpg;
5273 	int i;
5274 
5275 	if (mod->free_sgpgs < nsgpgs)
5276 		return BFA_STATUS_ENOMEM;
5277 
5278 	for (i = 0; i < nsgpgs; i++) {
5279 		bfa_q_deq(&mod->sgpg_q, &hsgpg);
5280 		WARN_ON(!hsgpg);
5281 		list_add_tail(&hsgpg->qe, sgpg_q);
5282 	}
5283 
5284 	mod->free_sgpgs -= nsgpgs;
5285 	return BFA_STATUS_OK;
5286 }
5287 
5288 void
5289 bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg)
5290 {
5291 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5292 	struct bfa_sgpg_wqe_s *wqe;
5293 
5294 	mod->free_sgpgs += nsgpg;
5295 	WARN_ON(mod->free_sgpgs > mod->num_sgpgs);
5296 
5297 	list_splice_tail_init(sgpg_q, &mod->sgpg_q);
5298 
5299 	if (list_empty(&mod->sgpg_wait_q))
5300 		return;
5301 
5302 	/*
5303 	 * satisfy as many waiting requests as possible
5304 	 */
5305 	do {
5306 		wqe = bfa_q_first(&mod->sgpg_wait_q);
5307 		if (mod->free_sgpgs < wqe->nsgpg)
5308 			nsgpg = mod->free_sgpgs;
5309 		else
5310 			nsgpg = wqe->nsgpg;
5311 		bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg);
5312 		wqe->nsgpg -= nsgpg;
5313 		if (wqe->nsgpg == 0) {
5314 			list_del(&wqe->qe);
5315 			wqe->cbfn(wqe->cbarg);
5316 		}
5317 	} while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q));
5318 }
5319 
5320 void
5321 bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg)
5322 {
5323 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5324 
5325 	WARN_ON(nsgpg <= 0);
5326 	WARN_ON(nsgpg <= mod->free_sgpgs);
5327 
5328 	wqe->nsgpg_total = wqe->nsgpg = nsgpg;
5329 
5330 	/*
5331 	 * allocate any left to this one first
5332 	 */
5333 	if (mod->free_sgpgs) {
5334 		/*
5335 		 * no one else is waiting for SGPG
5336 		 */
5337 		WARN_ON(!list_empty(&mod->sgpg_wait_q));
5338 		list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q);
5339 		wqe->nsgpg -= mod->free_sgpgs;
5340 		mod->free_sgpgs = 0;
5341 	}
5342 
5343 	list_add_tail(&wqe->qe, &mod->sgpg_wait_q);
5344 }
5345 
5346 void
5347 bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe)
5348 {
5349 	struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa);
5350 
5351 	WARN_ON(!bfa_q_is_on_q(&mod->sgpg_wait_q, wqe));
5352 	list_del(&wqe->qe);
5353 
5354 	if (wqe->nsgpg_total != wqe->nsgpg)
5355 		bfa_sgpg_mfree(bfa, &wqe->sgpg_q,
5356 				   wqe->nsgpg_total - wqe->nsgpg);
5357 }
5358 
5359 void
5360 bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg),
5361 		   void *cbarg)
5362 {
5363 	INIT_LIST_HEAD(&wqe->sgpg_q);
5364 	wqe->cbfn = cbfn;
5365 	wqe->cbarg = cbarg;
5366 }
5367 
5368 /*
5369  *  UF related functions
5370  */
5371 /*
5372  *****************************************************************************
5373  * Internal functions
5374  *****************************************************************************
5375  */
5376 static void
5377 __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete)
5378 {
5379 	struct bfa_uf_s   *uf = cbarg;
5380 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa);
5381 
5382 	if (complete)
5383 		ufm->ufrecv(ufm->cbarg, uf);
5384 }
5385 
5386 static void
5387 claim_uf_post_msgs(struct bfa_uf_mod_s *ufm)
5388 {
5389 	struct bfi_uf_buf_post_s *uf_bp_msg;
5390 	u16 i;
5391 	u16 buf_len;
5392 
5393 	ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_mem_kva_curp(ufm);
5394 	uf_bp_msg = ufm->uf_buf_posts;
5395 
5396 	for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs;
5397 	     i++, uf_bp_msg++) {
5398 		memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s));
5399 
5400 		uf_bp_msg->buf_tag = i;
5401 		buf_len = sizeof(struct bfa_uf_buf_s);
5402 		uf_bp_msg->buf_len = cpu_to_be16(buf_len);
5403 		bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST,
5404 			    bfa_fn_lpu(ufm->bfa));
5405 		bfa_alen_set(&uf_bp_msg->alen, buf_len, ufm_pbs_pa(ufm, i));
5406 	}
5407 
5408 	/*
5409 	 * advance pointer beyond consumed memory
5410 	 */
5411 	bfa_mem_kva_curp(ufm) = (u8 *) uf_bp_msg;
5412 }
5413 
5414 static void
5415 claim_ufs(struct bfa_uf_mod_s *ufm)
5416 {
5417 	u16 i;
5418 	struct bfa_uf_s   *uf;
5419 
5420 	/*
5421 	 * Claim block of memory for UF list
5422 	 */
5423 	ufm->uf_list = (struct bfa_uf_s *) bfa_mem_kva_curp(ufm);
5424 
5425 	/*
5426 	 * Initialize UFs and queue it in UF free queue
5427 	 */
5428 	for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) {
5429 		memset(uf, 0, sizeof(struct bfa_uf_s));
5430 		uf->bfa = ufm->bfa;
5431 		uf->uf_tag = i;
5432 		uf->pb_len = BFA_PER_UF_DMA_SZ;
5433 		uf->buf_kva = bfa_mem_get_dmabuf_kva(ufm, i, BFA_PER_UF_DMA_SZ);
5434 		uf->buf_pa = ufm_pbs_pa(ufm, i);
5435 		list_add_tail(&uf->qe, &ufm->uf_free_q);
5436 	}
5437 
5438 	/*
5439 	 * advance memory pointer
5440 	 */
5441 	bfa_mem_kva_curp(ufm) = (u8 *) uf;
5442 }
5443 
5444 static void
5445 uf_mem_claim(struct bfa_uf_mod_s *ufm)
5446 {
5447 	claim_ufs(ufm);
5448 	claim_uf_post_msgs(ufm);
5449 }
5450 
5451 void
5452 bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *minfo,
5453 		struct bfa_s *bfa)
5454 {
5455 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5456 	struct bfa_mem_kva_s *uf_kva = BFA_MEM_UF_KVA(bfa);
5457 	u32	num_ufs = cfg->fwcfg.num_uf_bufs;
5458 	struct bfa_mem_dma_s *seg_ptr;
5459 	u16	nsegs, idx, per_seg_uf = 0;
5460 
5461 	nsegs = BFI_MEM_DMA_NSEGS(num_ufs, BFA_PER_UF_DMA_SZ);
5462 	per_seg_uf = BFI_MEM_NREQS_SEG(BFA_PER_UF_DMA_SZ);
5463 
5464 	bfa_mem_dma_seg_iter(ufm, seg_ptr, nsegs, idx) {
5465 		if (num_ufs >= per_seg_uf) {
5466 			num_ufs -= per_seg_uf;
5467 			bfa_mem_dma_setup(minfo, seg_ptr,
5468 				per_seg_uf * BFA_PER_UF_DMA_SZ);
5469 		} else
5470 			bfa_mem_dma_setup(minfo, seg_ptr,
5471 				num_ufs * BFA_PER_UF_DMA_SZ);
5472 	}
5473 
5474 	/* kva memory */
5475 	bfa_mem_kva_setup(minfo, uf_kva, cfg->fwcfg.num_uf_bufs *
5476 		(sizeof(struct bfa_uf_s) + sizeof(struct bfi_uf_buf_post_s)));
5477 }
5478 
5479 void
5480 bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5481 		struct bfa_pcidev_s *pcidev)
5482 {
5483 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5484 
5485 	ufm->bfa = bfa;
5486 	ufm->num_ufs = cfg->fwcfg.num_uf_bufs;
5487 	INIT_LIST_HEAD(&ufm->uf_free_q);
5488 	INIT_LIST_HEAD(&ufm->uf_posted_q);
5489 	INIT_LIST_HEAD(&ufm->uf_unused_q);
5490 
5491 	uf_mem_claim(ufm);
5492 }
5493 
5494 static struct bfa_uf_s *
5495 bfa_uf_get(struct bfa_uf_mod_s *uf_mod)
5496 {
5497 	struct bfa_uf_s   *uf;
5498 
5499 	bfa_q_deq(&uf_mod->uf_free_q, &uf);
5500 	return uf;
5501 }
5502 
5503 static void
5504 bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf)
5505 {
5506 	list_add_tail(&uf->qe, &uf_mod->uf_free_q);
5507 }
5508 
5509 static bfa_status_t
5510 bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf)
5511 {
5512 	struct bfi_uf_buf_post_s *uf_post_msg;
5513 
5514 	uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP);
5515 	if (!uf_post_msg)
5516 		return BFA_STATUS_FAILED;
5517 
5518 	memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag],
5519 		      sizeof(struct bfi_uf_buf_post_s));
5520 	bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP, uf_post_msg->mh);
5521 
5522 	bfa_trc(ufm->bfa, uf->uf_tag);
5523 
5524 	list_add_tail(&uf->qe, &ufm->uf_posted_q);
5525 	return BFA_STATUS_OK;
5526 }
5527 
5528 static void
5529 bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod)
5530 {
5531 	struct bfa_uf_s   *uf;
5532 
5533 	while ((uf = bfa_uf_get(uf_mod)) != NULL) {
5534 		if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK)
5535 			break;
5536 	}
5537 }
5538 
5539 static void
5540 uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m)
5541 {
5542 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5543 	u16 uf_tag = m->buf_tag;
5544 	struct bfa_uf_s *uf = &ufm->uf_list[uf_tag];
5545 	struct bfa_uf_buf_s *uf_buf;
5546 	uint8_t *buf;
5547 	struct fchs_s *fchs;
5548 
5549 	uf_buf = (struct bfa_uf_buf_s *)
5550 			bfa_mem_get_dmabuf_kva(ufm, uf_tag, uf->pb_len);
5551 	buf = &uf_buf->d[0];
5552 
5553 	m->frm_len = be16_to_cpu(m->frm_len);
5554 	m->xfr_len = be16_to_cpu(m->xfr_len);
5555 
5556 	fchs = (struct fchs_s *)uf_buf;
5557 
5558 	list_del(&uf->qe);	/* dequeue from posted queue */
5559 
5560 	uf->data_ptr = buf;
5561 	uf->data_len = m->xfr_len;
5562 
5563 	WARN_ON(uf->data_len < sizeof(struct fchs_s));
5564 
5565 	if (uf->data_len == sizeof(struct fchs_s)) {
5566 		bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX,
5567 			       uf->data_len, (struct fchs_s *)buf);
5568 	} else {
5569 		u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s)));
5570 		bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF,
5571 				      BFA_PL_EID_RX, uf->data_len,
5572 				      (struct fchs_s *)buf, pld_w0);
5573 	}
5574 
5575 	if (bfa->fcs)
5576 		__bfa_cb_uf_recv(uf, BFA_TRUE);
5577 	else
5578 		bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf);
5579 }
5580 
5581 void
5582 bfa_uf_iocdisable(struct bfa_s *bfa)
5583 {
5584 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5585 	struct bfa_uf_s *uf;
5586 	struct list_head *qe, *qen;
5587 
5588 	/* Enqueue unused uf resources to free_q */
5589 	list_splice_tail_init(&ufm->uf_unused_q, &ufm->uf_free_q);
5590 
5591 	list_for_each_safe(qe, qen, &ufm->uf_posted_q) {
5592 		uf = (struct bfa_uf_s *) qe;
5593 		list_del(&uf->qe);
5594 		bfa_uf_put(ufm, uf);
5595 	}
5596 }
5597 
5598 void
5599 bfa_uf_start(struct bfa_s *bfa)
5600 {
5601 	bfa_uf_post_all(BFA_UF_MOD(bfa));
5602 }
5603 
5604 /*
5605  * Register handler for all unsolicted receive frames.
5606  *
5607  * @param[in]	bfa		BFA instance
5608  * @param[in]	ufrecv	receive handler function
5609  * @param[in]	cbarg	receive handler arg
5610  */
5611 void
5612 bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg)
5613 {
5614 	struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa);
5615 
5616 	ufm->ufrecv = ufrecv;
5617 	ufm->cbarg = cbarg;
5618 }
5619 
5620 /*
5621  *	Free an unsolicited frame back to BFA.
5622  *
5623  * @param[in]		uf		unsolicited frame to be freed
5624  *
5625  * @return None
5626  */
5627 void
5628 bfa_uf_free(struct bfa_uf_s *uf)
5629 {
5630 	bfa_uf_put(BFA_UF_MOD(uf->bfa), uf);
5631 	bfa_uf_post_all(BFA_UF_MOD(uf->bfa));
5632 }
5633 
5634 
5635 
5636 /*
5637  *  uf_pub BFA uf module public functions
5638  */
5639 void
5640 bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5641 {
5642 	bfa_trc(bfa, msg->mhdr.msg_id);
5643 
5644 	switch (msg->mhdr.msg_id) {
5645 	case BFI_UF_I2H_FRM_RCVD:
5646 		uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg);
5647 		break;
5648 
5649 	default:
5650 		bfa_trc(bfa, msg->mhdr.msg_id);
5651 		WARN_ON(1);
5652 	}
5653 }
5654 
5655 void
5656 bfa_uf_res_recfg(struct bfa_s *bfa, u16 num_uf_fw)
5657 {
5658 	struct bfa_uf_mod_s	*mod = BFA_UF_MOD(bfa);
5659 	struct list_head	*qe;
5660 	int	i;
5661 
5662 	for (i = 0; i < (mod->num_ufs - num_uf_fw); i++) {
5663 		bfa_q_deq_tail(&mod->uf_free_q, &qe);
5664 		list_add_tail(qe, &mod->uf_unused_q);
5665 	}
5666 }
5667 
5668 /*
5669  *	Dport forward declaration
5670  */
5671 
5672 enum bfa_dport_test_state_e {
5673 	BFA_DPORT_ST_DISABLED	= 0,	/*!< dport is disabled */
5674 	BFA_DPORT_ST_INP	= 1,	/*!< test in progress */
5675 	BFA_DPORT_ST_COMP	= 2,	/*!< test complete successfully */
5676 	BFA_DPORT_ST_NO_SFP	= 3,	/*!< sfp is not present */
5677 	BFA_DPORT_ST_NOTSTART	= 4,	/*!< test not start dport is enabled */
5678 };
5679 
5680 /*
5681  * BFA DPORT state machine events
5682  */
5683 enum bfa_dport_sm_event {
5684 	BFA_DPORT_SM_ENABLE	= 1,	/* dport enable event         */
5685 	BFA_DPORT_SM_DISABLE    = 2,    /* dport disable event        */
5686 	BFA_DPORT_SM_FWRSP      = 3,    /* fw enable/disable rsp      */
5687 	BFA_DPORT_SM_QRESUME    = 4,    /* CQ space available         */
5688 	BFA_DPORT_SM_HWFAIL     = 5,    /* IOC h/w failure            */
5689 	BFA_DPORT_SM_START	= 6,	/* re-start dport test        */
5690 	BFA_DPORT_SM_REQFAIL	= 7,	/* request failure            */
5691 	BFA_DPORT_SM_SCN	= 8,	/* state change notify frm fw */
5692 };
5693 
5694 static void bfa_dport_sm_disabled(struct bfa_dport_s *dport,
5695 				  enum bfa_dport_sm_event event);
5696 static void bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
5697 				  enum bfa_dport_sm_event event);
5698 static void bfa_dport_sm_enabling(struct bfa_dport_s *dport,
5699 				  enum bfa_dport_sm_event event);
5700 static void bfa_dport_sm_enabled(struct bfa_dport_s *dport,
5701 				 enum bfa_dport_sm_event event);
5702 static void bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
5703 				 enum bfa_dport_sm_event event);
5704 static void bfa_dport_sm_disabling(struct bfa_dport_s *dport,
5705 				   enum bfa_dport_sm_event event);
5706 static void bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
5707 					enum bfa_dport_sm_event event);
5708 static void bfa_dport_sm_starting(struct bfa_dport_s *dport,
5709 				  enum bfa_dport_sm_event event);
5710 static void bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
5711 				   enum bfa_dport_sm_event event);
5712 static void bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
5713 				   enum bfa_dport_sm_event event);
5714 static void bfa_dport_qresume(void *cbarg);
5715 static void bfa_dport_req_comp(struct bfa_dport_s *dport,
5716 				struct bfi_diag_dport_rsp_s *msg);
5717 static void bfa_dport_scn(struct bfa_dport_s *dport,
5718 				struct bfi_diag_dport_scn_s *msg);
5719 
5720 /*
5721  *	BFA fcdiag module
5722  */
5723 #define BFA_DIAG_QTEST_TOV	1000    /* msec */
5724 
5725 /*
5726  *	Set port status to busy
5727  */
5728 static void
5729 bfa_fcdiag_set_busy_status(struct bfa_fcdiag_s *fcdiag)
5730 {
5731 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(fcdiag->bfa);
5732 
5733 	if (fcdiag->lb.lock)
5734 		fcport->diag_busy = BFA_TRUE;
5735 	else
5736 		fcport->diag_busy = BFA_FALSE;
5737 }
5738 
5739 void
5740 bfa_fcdiag_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5741 		struct bfa_pcidev_s *pcidev)
5742 {
5743 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5744 	struct bfa_dport_s  *dport = &fcdiag->dport;
5745 
5746 	fcdiag->bfa             = bfa;
5747 	fcdiag->trcmod  = bfa->trcmod;
5748 	/* The common DIAG attach bfa_diag_attach() will do all memory claim */
5749 	dport->bfa = bfa;
5750 	bfa_sm_set_state(dport, bfa_dport_sm_disabled);
5751 	bfa_reqq_winit(&dport->reqq_wait, bfa_dport_qresume, dport);
5752 	dport->cbfn = NULL;
5753 	dport->cbarg = NULL;
5754 	dport->test_state = BFA_DPORT_ST_DISABLED;
5755 	memset(&dport->result, 0, sizeof(struct bfa_diag_dport_result_s));
5756 }
5757 
5758 void
5759 bfa_fcdiag_iocdisable(struct bfa_s *bfa)
5760 {
5761 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5762 	struct bfa_dport_s *dport = &fcdiag->dport;
5763 
5764 	bfa_trc(fcdiag, fcdiag->lb.lock);
5765 	if (fcdiag->lb.lock) {
5766 		fcdiag->lb.status = BFA_STATUS_IOC_FAILURE;
5767 		fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5768 		fcdiag->lb.lock = 0;
5769 		bfa_fcdiag_set_busy_status(fcdiag);
5770 	}
5771 
5772 	bfa_sm_send_event(dport, BFA_DPORT_SM_HWFAIL);
5773 }
5774 
5775 static void
5776 bfa_fcdiag_queuetest_timeout(void *cbarg)
5777 {
5778 	struct bfa_fcdiag_s       *fcdiag = cbarg;
5779 	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5780 
5781 	bfa_trc(fcdiag, fcdiag->qtest.all);
5782 	bfa_trc(fcdiag, fcdiag->qtest.count);
5783 
5784 	fcdiag->qtest.timer_active = 0;
5785 
5786 	res->status = BFA_STATUS_ETIMER;
5787 	res->count  = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5788 	if (fcdiag->qtest.all)
5789 		res->queue  = fcdiag->qtest.all;
5790 
5791 	bfa_trc(fcdiag, BFA_STATUS_ETIMER);
5792 	fcdiag->qtest.status = BFA_STATUS_ETIMER;
5793 	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5794 	fcdiag->qtest.lock = 0;
5795 }
5796 
5797 static bfa_status_t
5798 bfa_fcdiag_queuetest_send(struct bfa_fcdiag_s *fcdiag)
5799 {
5800 	u32	i;
5801 	struct bfi_diag_qtest_req_s *req;
5802 
5803 	req = bfa_reqq_next(fcdiag->bfa, fcdiag->qtest.queue);
5804 	if (!req)
5805 		return BFA_STATUS_DEVBUSY;
5806 
5807 	/* build host command */
5808 	bfi_h2i_set(req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_QTEST,
5809 		bfa_fn_lpu(fcdiag->bfa));
5810 
5811 	for (i = 0; i < BFI_LMSG_PL_WSZ; i++)
5812 		req->data[i] = QTEST_PAT_DEFAULT;
5813 
5814 	bfa_trc(fcdiag, fcdiag->qtest.queue);
5815 	/* ring door bell */
5816 	bfa_reqq_produce(fcdiag->bfa, fcdiag->qtest.queue, req->mh);
5817 	return BFA_STATUS_OK;
5818 }
5819 
5820 static void
5821 bfa_fcdiag_queuetest_comp(struct bfa_fcdiag_s *fcdiag,
5822 			bfi_diag_qtest_rsp_t *rsp)
5823 {
5824 	struct bfa_diag_qtest_result_s *res = fcdiag->qtest.result;
5825 	bfa_status_t status = BFA_STATUS_OK;
5826 	int i;
5827 
5828 	/* Check timer, should still be active   */
5829 	if (!fcdiag->qtest.timer_active) {
5830 		bfa_trc(fcdiag, fcdiag->qtest.timer_active);
5831 		return;
5832 	}
5833 
5834 	/* update count */
5835 	fcdiag->qtest.count--;
5836 
5837 	/* Check result */
5838 	for (i = 0; i < BFI_LMSG_PL_WSZ; i++) {
5839 		if (rsp->data[i] != ~(QTEST_PAT_DEFAULT)) {
5840 			res->status = BFA_STATUS_DATACORRUPTED;
5841 			break;
5842 		}
5843 	}
5844 
5845 	if (res->status == BFA_STATUS_OK) {
5846 		if (fcdiag->qtest.count > 0) {
5847 			status = bfa_fcdiag_queuetest_send(fcdiag);
5848 			if (status == BFA_STATUS_OK)
5849 				return;
5850 			else
5851 				res->status = status;
5852 		} else if (fcdiag->qtest.all > 0 &&
5853 			fcdiag->qtest.queue < (BFI_IOC_MAX_CQS - 1)) {
5854 			fcdiag->qtest.count = QTEST_CNT_DEFAULT;
5855 			fcdiag->qtest.queue++;
5856 			status = bfa_fcdiag_queuetest_send(fcdiag);
5857 			if (status == BFA_STATUS_OK)
5858 				return;
5859 			else
5860 				res->status = status;
5861 		}
5862 	}
5863 
5864 	/* Stop timer when we comp all queue */
5865 	if (fcdiag->qtest.timer_active) {
5866 		bfa_timer_stop(&fcdiag->qtest.timer);
5867 		fcdiag->qtest.timer_active = 0;
5868 	}
5869 	res->queue = fcdiag->qtest.queue;
5870 	res->count = QTEST_CNT_DEFAULT - fcdiag->qtest.count;
5871 	bfa_trc(fcdiag, res->count);
5872 	bfa_trc(fcdiag, res->status);
5873 	fcdiag->qtest.status = res->status;
5874 	fcdiag->qtest.cbfn(fcdiag->qtest.cbarg, fcdiag->qtest.status);
5875 	fcdiag->qtest.lock = 0;
5876 }
5877 
5878 static void
5879 bfa_fcdiag_loopback_comp(struct bfa_fcdiag_s *fcdiag,
5880 			struct bfi_diag_lb_rsp_s *rsp)
5881 {
5882 	struct bfa_diag_loopback_result_s *res = fcdiag->lb.result;
5883 
5884 	res->numtxmfrm  = be32_to_cpu(rsp->res.numtxmfrm);
5885 	res->numosffrm  = be32_to_cpu(rsp->res.numosffrm);
5886 	res->numrcvfrm  = be32_to_cpu(rsp->res.numrcvfrm);
5887 	res->badfrminf  = be32_to_cpu(rsp->res.badfrminf);
5888 	res->badfrmnum  = be32_to_cpu(rsp->res.badfrmnum);
5889 	res->status     = rsp->res.status;
5890 	fcdiag->lb.status = rsp->res.status;
5891 	bfa_trc(fcdiag, fcdiag->lb.status);
5892 	fcdiag->lb.cbfn(fcdiag->lb.cbarg, fcdiag->lb.status);
5893 	fcdiag->lb.lock = 0;
5894 	bfa_fcdiag_set_busy_status(fcdiag);
5895 }
5896 
5897 static bfa_status_t
5898 bfa_fcdiag_loopback_send(struct bfa_fcdiag_s *fcdiag,
5899 			struct bfa_diag_loopback_s *loopback)
5900 {
5901 	struct bfi_diag_lb_req_s *lb_req;
5902 
5903 	lb_req = bfa_reqq_next(fcdiag->bfa, BFA_REQQ_DIAG);
5904 	if (!lb_req)
5905 		return BFA_STATUS_DEVBUSY;
5906 
5907 	/* build host command */
5908 	bfi_h2i_set(lb_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LOOPBACK,
5909 		bfa_fn_lpu(fcdiag->bfa));
5910 
5911 	lb_req->lb_mode = loopback->lb_mode;
5912 	lb_req->speed = loopback->speed;
5913 	lb_req->loopcnt = loopback->loopcnt;
5914 	lb_req->pattern = loopback->pattern;
5915 
5916 	/* ring door bell */
5917 	bfa_reqq_produce(fcdiag->bfa, BFA_REQQ_DIAG, lb_req->mh);
5918 
5919 	bfa_trc(fcdiag, loopback->lb_mode);
5920 	bfa_trc(fcdiag, loopback->speed);
5921 	bfa_trc(fcdiag, loopback->loopcnt);
5922 	bfa_trc(fcdiag, loopback->pattern);
5923 	return BFA_STATUS_OK;
5924 }
5925 
5926 /*
5927  *	cpe/rme intr handler
5928  */
5929 void
5930 bfa_fcdiag_intr(struct bfa_s *bfa, struct bfi_msg_s *msg)
5931 {
5932 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5933 
5934 	switch (msg->mhdr.msg_id) {
5935 	case BFI_DIAG_I2H_LOOPBACK:
5936 		bfa_fcdiag_loopback_comp(fcdiag,
5937 				(struct bfi_diag_lb_rsp_s *) msg);
5938 		break;
5939 	case BFI_DIAG_I2H_QTEST:
5940 		bfa_fcdiag_queuetest_comp(fcdiag, (bfi_diag_qtest_rsp_t *)msg);
5941 		break;
5942 	case BFI_DIAG_I2H_DPORT:
5943 		bfa_dport_req_comp(&fcdiag->dport,
5944 				(struct bfi_diag_dport_rsp_s *)msg);
5945 		break;
5946 	case BFI_DIAG_I2H_DPORT_SCN:
5947 		bfa_dport_scn(&fcdiag->dport,
5948 				(struct bfi_diag_dport_scn_s *)msg);
5949 		break;
5950 	default:
5951 		bfa_trc(fcdiag, msg->mhdr.msg_id);
5952 		WARN_ON(1);
5953 	}
5954 }
5955 
5956 /*
5957  *	Loopback test
5958  *
5959  *   @param[in] *bfa            - bfa data struct
5960  *   @param[in] opmode          - port operation mode
5961  *   @param[in] speed           - port speed
5962  *   @param[in] lpcnt           - loop count
5963  *   @param[in] pat                     - pattern to build packet
5964  *   @param[in] *result         - pt to bfa_diag_loopback_result_t data struct
5965  *   @param[in] cbfn            - callback function
5966  *   @param[in] cbarg           - callback functioin arg
5967  *
5968  *   @param[out]
5969  */
5970 bfa_status_t
5971 bfa_fcdiag_loopback(struct bfa_s *bfa, enum bfa_port_opmode opmode,
5972 		enum bfa_port_speed speed, u32 lpcnt, u32 pat,
5973 		struct bfa_diag_loopback_result_s *result, bfa_cb_diag_t cbfn,
5974 		void *cbarg)
5975 {
5976 	struct  bfa_diag_loopback_s loopback;
5977 	struct bfa_port_attr_s attr;
5978 	bfa_status_t status;
5979 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
5980 
5981 	if (!bfa_iocfc_is_operational(bfa))
5982 		return BFA_STATUS_IOC_NON_OP;
5983 
5984 	/* if port is PBC disabled, return error */
5985 	if (bfa_fcport_is_pbcdisabled(bfa)) {
5986 		bfa_trc(fcdiag, BFA_STATUS_PBC);
5987 		return BFA_STATUS_PBC;
5988 	}
5989 
5990 	if (bfa_fcport_is_disabled(bfa) == BFA_FALSE) {
5991 		bfa_trc(fcdiag, opmode);
5992 		return BFA_STATUS_PORT_NOT_DISABLED;
5993 	}
5994 
5995 	/*
5996 	 * Check if input speed is supported by the port mode
5997 	 */
5998 	if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
5999 		if (!(speed == BFA_PORT_SPEED_1GBPS ||
6000 		      speed == BFA_PORT_SPEED_2GBPS ||
6001 		      speed == BFA_PORT_SPEED_4GBPS ||
6002 		      speed == BFA_PORT_SPEED_8GBPS ||
6003 		      speed == BFA_PORT_SPEED_16GBPS ||
6004 		      speed == BFA_PORT_SPEED_AUTO)) {
6005 			bfa_trc(fcdiag, speed);
6006 			return BFA_STATUS_UNSUPP_SPEED;
6007 		}
6008 		bfa_fcport_get_attr(bfa, &attr);
6009 		bfa_trc(fcdiag, attr.speed_supported);
6010 		if (speed > attr.speed_supported)
6011 			return BFA_STATUS_UNSUPP_SPEED;
6012 	} else {
6013 		if (speed != BFA_PORT_SPEED_10GBPS) {
6014 			bfa_trc(fcdiag, speed);
6015 			return BFA_STATUS_UNSUPP_SPEED;
6016 		}
6017 	}
6018 
6019 	/*
6020 	 * For CT2, 1G is not supported
6021 	 */
6022 	if ((speed == BFA_PORT_SPEED_1GBPS) &&
6023 	    (bfa_asic_id_ct2(bfa->ioc.pcidev.device_id))) {
6024 		bfa_trc(fcdiag, speed);
6025 		return BFA_STATUS_UNSUPP_SPEED;
6026 	}
6027 
6028 	/* For Mezz card, port speed entered needs to be checked */
6029 	if (bfa_mfg_is_mezz(bfa->ioc.attr->card_type)) {
6030 		if (bfa_ioc_get_type(&bfa->ioc) == BFA_IOC_TYPE_FC) {
6031 			if (!(speed == BFA_PORT_SPEED_1GBPS ||
6032 			      speed == BFA_PORT_SPEED_2GBPS ||
6033 			      speed == BFA_PORT_SPEED_4GBPS ||
6034 			      speed == BFA_PORT_SPEED_8GBPS ||
6035 			      speed == BFA_PORT_SPEED_16GBPS ||
6036 			      speed == BFA_PORT_SPEED_AUTO))
6037 				return BFA_STATUS_UNSUPP_SPEED;
6038 		} else {
6039 			if (speed != BFA_PORT_SPEED_10GBPS)
6040 				return BFA_STATUS_UNSUPP_SPEED;
6041 		}
6042 	}
6043 	/* check to see if fcport is dport */
6044 	if (bfa_fcport_is_dport(bfa)) {
6045 		bfa_trc(fcdiag, fcdiag->lb.lock);
6046 		return BFA_STATUS_DPORT_ENABLED;
6047 	}
6048 	/* check to see if there is another destructive diag cmd running */
6049 	if (fcdiag->lb.lock) {
6050 		bfa_trc(fcdiag, fcdiag->lb.lock);
6051 		return BFA_STATUS_DEVBUSY;
6052 	}
6053 
6054 	fcdiag->lb.lock = 1;
6055 	loopback.lb_mode = opmode;
6056 	loopback.speed = speed;
6057 	loopback.loopcnt = lpcnt;
6058 	loopback.pattern = pat;
6059 	fcdiag->lb.result = result;
6060 	fcdiag->lb.cbfn = cbfn;
6061 	fcdiag->lb.cbarg = cbarg;
6062 	memset(result, 0, sizeof(struct bfa_diag_loopback_result_s));
6063 	bfa_fcdiag_set_busy_status(fcdiag);
6064 
6065 	/* Send msg to fw */
6066 	status = bfa_fcdiag_loopback_send(fcdiag, &loopback);
6067 	return status;
6068 }
6069 
6070 /*
6071  *	DIAG queue test command
6072  *
6073  *   @param[in] *bfa            - bfa data struct
6074  *   @param[in] force           - 1: don't do ioc op checking
6075  *   @param[in] queue           - queue no. to test
6076  *   @param[in] *result         - pt to bfa_diag_qtest_result_t data struct
6077  *   @param[in] cbfn            - callback function
6078  *   @param[in] *cbarg          - callback functioin arg
6079  *
6080  *   @param[out]
6081  */
6082 bfa_status_t
6083 bfa_fcdiag_queuetest(struct bfa_s *bfa, u32 force, u32 queue,
6084 		struct bfa_diag_qtest_result_s *result, bfa_cb_diag_t cbfn,
6085 		void *cbarg)
6086 {
6087 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6088 	bfa_status_t status;
6089 	bfa_trc(fcdiag, force);
6090 	bfa_trc(fcdiag, queue);
6091 
6092 	if (!force && !bfa_iocfc_is_operational(bfa))
6093 		return BFA_STATUS_IOC_NON_OP;
6094 
6095 	/* check to see if there is another destructive diag cmd running */
6096 	if (fcdiag->qtest.lock) {
6097 		bfa_trc(fcdiag, fcdiag->qtest.lock);
6098 		return BFA_STATUS_DEVBUSY;
6099 	}
6100 
6101 	/* Initialization */
6102 	fcdiag->qtest.lock = 1;
6103 	fcdiag->qtest.cbfn = cbfn;
6104 	fcdiag->qtest.cbarg = cbarg;
6105 	fcdiag->qtest.result = result;
6106 	fcdiag->qtest.count = QTEST_CNT_DEFAULT;
6107 
6108 	/* Init test results */
6109 	fcdiag->qtest.result->status = BFA_STATUS_OK;
6110 	fcdiag->qtest.result->count  = 0;
6111 
6112 	/* send */
6113 	if (queue < BFI_IOC_MAX_CQS) {
6114 		fcdiag->qtest.result->queue  = (u8)queue;
6115 		fcdiag->qtest.queue = (u8)queue;
6116 		fcdiag->qtest.all   = 0;
6117 	} else {
6118 		fcdiag->qtest.result->queue  = 0;
6119 		fcdiag->qtest.queue = 0;
6120 		fcdiag->qtest.all   = 1;
6121 	}
6122 	status = bfa_fcdiag_queuetest_send(fcdiag);
6123 
6124 	/* Start a timer */
6125 	if (status == BFA_STATUS_OK) {
6126 		bfa_timer_start(bfa, &fcdiag->qtest.timer,
6127 				bfa_fcdiag_queuetest_timeout, fcdiag,
6128 				BFA_DIAG_QTEST_TOV);
6129 		fcdiag->qtest.timer_active = 1;
6130 	}
6131 	return status;
6132 }
6133 
6134 /*
6135  * DIAG PLB is running
6136  *
6137  *   @param[in] *bfa    - bfa data struct
6138  *
6139  *   @param[out]
6140  */
6141 bfa_status_t
6142 bfa_fcdiag_lb_is_running(struct bfa_s *bfa)
6143 {
6144 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6145 	return fcdiag->lb.lock ?  BFA_STATUS_DIAG_BUSY : BFA_STATUS_OK;
6146 }
6147 
6148 /*
6149  *	D-port
6150  */
6151 #define bfa_dport_result_start(__dport, __mode) do {			\
6152 		(__dport)->result.start_time = bfa_get_log_time();	\
6153 		(__dport)->result.status = DPORT_TEST_ST_INPRG;		\
6154 		(__dport)->result.mode = (__mode);			\
6155 		(__dport)->result.rp_pwwn = (__dport)->rp_pwwn;		\
6156 		(__dport)->result.rp_nwwn = (__dport)->rp_nwwn;		\
6157 		(__dport)->result.lpcnt = (__dport)->lpcnt;		\
6158 } while (0)
6159 
6160 static bfa_boolean_t bfa_dport_send_req(struct bfa_dport_s *dport,
6161 					enum bfi_dport_req req);
6162 static void
6163 bfa_cb_fcdiag_dport(struct bfa_dport_s *dport, bfa_status_t bfa_status)
6164 {
6165 	if (dport->cbfn != NULL) {
6166 		dport->cbfn(dport->cbarg, bfa_status);
6167 		dport->cbfn = NULL;
6168 		dport->cbarg = NULL;
6169 	}
6170 }
6171 
6172 static void
6173 bfa_dport_sm_disabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6174 {
6175 	bfa_trc(dport->bfa, event);
6176 
6177 	switch (event) {
6178 	case BFA_DPORT_SM_ENABLE:
6179 		bfa_fcport_dportenable(dport->bfa);
6180 		if (bfa_dport_send_req(dport, BFI_DPORT_ENABLE))
6181 			bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6182 		else
6183 			bfa_sm_set_state(dport, bfa_dport_sm_enabling_qwait);
6184 		break;
6185 
6186 	case BFA_DPORT_SM_DISABLE:
6187 		/* Already disabled */
6188 		break;
6189 
6190 	case BFA_DPORT_SM_HWFAIL:
6191 		/* ignore */
6192 		break;
6193 
6194 	case BFA_DPORT_SM_SCN:
6195 		if (dport->i2hmsg.scn.state ==  BFI_DPORT_SCN_DDPORT_ENABLE) {
6196 			bfa_fcport_ddportenable(dport->bfa);
6197 			dport->dynamic = BFA_TRUE;
6198 			dport->test_state = BFA_DPORT_ST_NOTSTART;
6199 			bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6200 		} else {
6201 			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6202 			WARN_ON(1);
6203 		}
6204 		break;
6205 
6206 	default:
6207 		bfa_sm_fault(dport->bfa, event);
6208 	}
6209 }
6210 
6211 static void
6212 bfa_dport_sm_enabling_qwait(struct bfa_dport_s *dport,
6213 			    enum bfa_dport_sm_event event)
6214 {
6215 	bfa_trc(dport->bfa, event);
6216 
6217 	switch (event) {
6218 	case BFA_DPORT_SM_QRESUME:
6219 		bfa_sm_set_state(dport, bfa_dport_sm_enabling);
6220 		bfa_dport_send_req(dport, BFI_DPORT_ENABLE);
6221 		break;
6222 
6223 	case BFA_DPORT_SM_HWFAIL:
6224 		bfa_reqq_wcancel(&dport->reqq_wait);
6225 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6226 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6227 		break;
6228 
6229 	default:
6230 		bfa_sm_fault(dport->bfa, event);
6231 	}
6232 }
6233 
6234 static void
6235 bfa_dport_sm_enabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6236 {
6237 	bfa_trc(dport->bfa, event);
6238 
6239 	switch (event) {
6240 	case BFA_DPORT_SM_FWRSP:
6241 		memset(&dport->result, 0,
6242 				sizeof(struct bfa_diag_dport_result_s));
6243 		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6244 			dport->test_state = BFA_DPORT_ST_NO_SFP;
6245 		} else {
6246 			dport->test_state = BFA_DPORT_ST_INP;
6247 			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_AUTO);
6248 		}
6249 		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6250 		break;
6251 
6252 	case BFA_DPORT_SM_REQFAIL:
6253 		dport->test_state = BFA_DPORT_ST_DISABLED;
6254 		bfa_fcport_dportdisable(dport->bfa);
6255 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6256 		break;
6257 
6258 	case BFA_DPORT_SM_HWFAIL:
6259 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6260 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6261 		break;
6262 
6263 	default:
6264 		bfa_sm_fault(dport->bfa, event);
6265 	}
6266 }
6267 
6268 static void
6269 bfa_dport_sm_enabled(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6270 {
6271 	bfa_trc(dport->bfa, event);
6272 
6273 	switch (event) {
6274 	case BFA_DPORT_SM_START:
6275 		if (bfa_dport_send_req(dport, BFI_DPORT_START))
6276 			bfa_sm_set_state(dport, bfa_dport_sm_starting);
6277 		else
6278 			bfa_sm_set_state(dport, bfa_dport_sm_starting_qwait);
6279 		break;
6280 
6281 	case BFA_DPORT_SM_DISABLE:
6282 		bfa_fcport_dportdisable(dport->bfa);
6283 		if (bfa_dport_send_req(dport, BFI_DPORT_DISABLE))
6284 			bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6285 		else
6286 			bfa_sm_set_state(dport, bfa_dport_sm_disabling_qwait);
6287 		break;
6288 
6289 	case BFA_DPORT_SM_HWFAIL:
6290 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6291 		break;
6292 
6293 	case BFA_DPORT_SM_SCN:
6294 		switch (dport->i2hmsg.scn.state) {
6295 		case BFI_DPORT_SCN_TESTCOMP:
6296 			dport->test_state = BFA_DPORT_ST_COMP;
6297 			break;
6298 
6299 		case BFI_DPORT_SCN_TESTSTART:
6300 			dport->test_state = BFA_DPORT_ST_INP;
6301 			break;
6302 
6303 		case BFI_DPORT_SCN_TESTSKIP:
6304 		case BFI_DPORT_SCN_SUBTESTSTART:
6305 			/* no state change */
6306 			break;
6307 
6308 		case BFI_DPORT_SCN_SFP_REMOVED:
6309 			dport->test_state = BFA_DPORT_ST_NO_SFP;
6310 			break;
6311 
6312 		case BFI_DPORT_SCN_DDPORT_DISABLE:
6313 			bfa_fcport_ddportdisable(dport->bfa);
6314 
6315 			if (bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE))
6316 				bfa_sm_set_state(dport,
6317 					 bfa_dport_sm_dynamic_disabling);
6318 			else
6319 				bfa_sm_set_state(dport,
6320 					 bfa_dport_sm_dynamic_disabling_qwait);
6321 			break;
6322 
6323 		case BFI_DPORT_SCN_FCPORT_DISABLE:
6324 			bfa_fcport_ddportdisable(dport->bfa);
6325 
6326 			bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6327 			dport->dynamic = BFA_FALSE;
6328 			break;
6329 
6330 		default:
6331 			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6332 			bfa_sm_fault(dport->bfa, event);
6333 		}
6334 		break;
6335 	default:
6336 		bfa_sm_fault(dport->bfa, event);
6337 	}
6338 }
6339 
6340 static void
6341 bfa_dport_sm_disabling_qwait(struct bfa_dport_s *dport,
6342 			     enum bfa_dport_sm_event event)
6343 {
6344 	bfa_trc(dport->bfa, event);
6345 
6346 	switch (event) {
6347 	case BFA_DPORT_SM_QRESUME:
6348 		bfa_sm_set_state(dport, bfa_dport_sm_disabling);
6349 		bfa_dport_send_req(dport, BFI_DPORT_DISABLE);
6350 		break;
6351 
6352 	case BFA_DPORT_SM_HWFAIL:
6353 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6354 		bfa_reqq_wcancel(&dport->reqq_wait);
6355 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6356 		break;
6357 
6358 	case BFA_DPORT_SM_SCN:
6359 		/* ignore */
6360 		break;
6361 
6362 	default:
6363 		bfa_sm_fault(dport->bfa, event);
6364 	}
6365 }
6366 
6367 static void
6368 bfa_dport_sm_disabling(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6369 {
6370 	bfa_trc(dport->bfa, event);
6371 
6372 	switch (event) {
6373 	case BFA_DPORT_SM_FWRSP:
6374 		dport->test_state = BFA_DPORT_ST_DISABLED;
6375 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6376 		break;
6377 
6378 	case BFA_DPORT_SM_HWFAIL:
6379 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6380 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6381 		break;
6382 
6383 	case BFA_DPORT_SM_SCN:
6384 		/* no state change */
6385 		break;
6386 
6387 	default:
6388 		bfa_sm_fault(dport->bfa, event);
6389 	}
6390 }
6391 
6392 static void
6393 bfa_dport_sm_starting_qwait(struct bfa_dport_s *dport,
6394 			    enum bfa_dport_sm_event event)
6395 {
6396 	bfa_trc(dport->bfa, event);
6397 
6398 	switch (event) {
6399 	case BFA_DPORT_SM_QRESUME:
6400 		bfa_sm_set_state(dport, bfa_dport_sm_starting);
6401 		bfa_dport_send_req(dport, BFI_DPORT_START);
6402 		break;
6403 
6404 	case BFA_DPORT_SM_HWFAIL:
6405 		bfa_reqq_wcancel(&dport->reqq_wait);
6406 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6407 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6408 		break;
6409 
6410 	default:
6411 		bfa_sm_fault(dport->bfa, event);
6412 	}
6413 }
6414 
6415 static void
6416 bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event)
6417 {
6418 	bfa_trc(dport->bfa, event);
6419 
6420 	switch (event) {
6421 	case BFA_DPORT_SM_FWRSP:
6422 		memset(&dport->result, 0,
6423 				sizeof(struct bfa_diag_dport_result_s));
6424 		if (dport->i2hmsg.rsp.status == BFA_STATUS_DPORT_INV_SFP) {
6425 			dport->test_state = BFA_DPORT_ST_NO_SFP;
6426 		} else {
6427 			dport->test_state = BFA_DPORT_ST_INP;
6428 			bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU);
6429 		}
6430 		/* fall thru */
6431 
6432 	case BFA_DPORT_SM_REQFAIL:
6433 		bfa_sm_set_state(dport, bfa_dport_sm_enabled);
6434 		break;
6435 
6436 	case BFA_DPORT_SM_HWFAIL:
6437 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6438 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_FAILED);
6439 		break;
6440 
6441 	default:
6442 		bfa_sm_fault(dport->bfa, event);
6443 	}
6444 }
6445 
6446 static void
6447 bfa_dport_sm_dynamic_disabling(struct bfa_dport_s *dport,
6448 			       enum bfa_dport_sm_event event)
6449 {
6450 	bfa_trc(dport->bfa, event);
6451 
6452 	switch (event) {
6453 	case BFA_DPORT_SM_SCN:
6454 		switch (dport->i2hmsg.scn.state) {
6455 		case BFI_DPORT_SCN_DDPORT_DISABLED:
6456 			bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6457 			dport->dynamic = BFA_FALSE;
6458 			bfa_fcport_enable(dport->bfa);
6459 			break;
6460 
6461 		default:
6462 			bfa_trc(dport->bfa, dport->i2hmsg.scn.state);
6463 			bfa_sm_fault(dport->bfa, event);
6464 
6465 		}
6466 		break;
6467 
6468 	case BFA_DPORT_SM_HWFAIL:
6469 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6470 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6471 		break;
6472 
6473 	default:
6474 		bfa_sm_fault(dport->bfa, event);
6475 	}
6476 }
6477 
6478 static void
6479 bfa_dport_sm_dynamic_disabling_qwait(struct bfa_dport_s *dport,
6480 			    enum bfa_dport_sm_event event)
6481 {
6482 	bfa_trc(dport->bfa, event);
6483 
6484 	switch (event) {
6485 	case BFA_DPORT_SM_QRESUME:
6486 		bfa_sm_set_state(dport, bfa_dport_sm_dynamic_disabling);
6487 		bfa_dport_send_req(dport, BFI_DPORT_DYN_DISABLE);
6488 		break;
6489 
6490 	case BFA_DPORT_SM_HWFAIL:
6491 		bfa_sm_set_state(dport, bfa_dport_sm_disabled);
6492 		bfa_reqq_wcancel(&dport->reqq_wait);
6493 		bfa_cb_fcdiag_dport(dport, BFA_STATUS_OK);
6494 		break;
6495 
6496 	case BFA_DPORT_SM_SCN:
6497 		/* ignore */
6498 		break;
6499 
6500 	default:
6501 		bfa_sm_fault(dport->bfa, event);
6502 	}
6503 }
6504 
6505 static bfa_boolean_t
6506 bfa_dport_send_req(struct bfa_dport_s *dport, enum bfi_dport_req req)
6507 {
6508 	struct bfi_diag_dport_req_s *m;
6509 
6510 	/*
6511 	 * check for room in queue to send request now
6512 	 */
6513 	m = bfa_reqq_next(dport->bfa, BFA_REQQ_DIAG);
6514 	if (!m) {
6515 		bfa_reqq_wait(dport->bfa, BFA_REQQ_PORT, &dport->reqq_wait);
6516 		return BFA_FALSE;
6517 	}
6518 
6519 	bfi_h2i_set(m->mh, BFI_MC_DIAG, BFI_DIAG_H2I_DPORT,
6520 		    bfa_fn_lpu(dport->bfa));
6521 	m->req  = req;
6522 	if ((req == BFI_DPORT_ENABLE) || (req == BFI_DPORT_START)) {
6523 		m->lpcnt = cpu_to_be32(dport->lpcnt);
6524 		m->payload = cpu_to_be32(dport->payload);
6525 	}
6526 
6527 	/*
6528 	 * queue I/O message to firmware
6529 	 */
6530 	bfa_reqq_produce(dport->bfa, BFA_REQQ_DIAG, m->mh);
6531 
6532 	return BFA_TRUE;
6533 }
6534 
6535 static void
6536 bfa_dport_qresume(void *cbarg)
6537 {
6538 	struct bfa_dport_s *dport = cbarg;
6539 
6540 	bfa_sm_send_event(dport, BFA_DPORT_SM_QRESUME);
6541 }
6542 
6543 static void
6544 bfa_dport_req_comp(struct bfa_dport_s *dport, struct bfi_diag_dport_rsp_s *msg)
6545 {
6546 	msg->status = cpu_to_be32(msg->status);
6547 	dport->i2hmsg.rsp.status = msg->status;
6548 	dport->rp_pwwn = msg->pwwn;
6549 	dport->rp_nwwn = msg->nwwn;
6550 
6551 	if ((msg->status == BFA_STATUS_OK) ||
6552 	    (msg->status == BFA_STATUS_DPORT_NO_SFP)) {
6553 		bfa_trc(dport->bfa, msg->status);
6554 		bfa_trc(dport->bfa, dport->rp_pwwn);
6555 		bfa_trc(dport->bfa, dport->rp_nwwn);
6556 		bfa_sm_send_event(dport, BFA_DPORT_SM_FWRSP);
6557 
6558 	} else {
6559 		bfa_trc(dport->bfa, msg->status);
6560 		bfa_sm_send_event(dport, BFA_DPORT_SM_REQFAIL);
6561 	}
6562 	bfa_cb_fcdiag_dport(dport, msg->status);
6563 }
6564 
6565 static bfa_boolean_t
6566 bfa_dport_is_sending_req(struct bfa_dport_s *dport)
6567 {
6568 	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabling)	||
6569 	    bfa_sm_cmp_state(dport, bfa_dport_sm_enabling_qwait) ||
6570 	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling)	||
6571 	    bfa_sm_cmp_state(dport, bfa_dport_sm_disabling_qwait) ||
6572 	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting)	||
6573 	    bfa_sm_cmp_state(dport, bfa_dport_sm_starting_qwait)) {
6574 		return BFA_TRUE;
6575 	} else {
6576 		return BFA_FALSE;
6577 	}
6578 }
6579 
6580 static void
6581 bfa_dport_scn(struct bfa_dport_s *dport, struct bfi_diag_dport_scn_s *msg)
6582 {
6583 	int i;
6584 	uint8_t subtesttype;
6585 
6586 	bfa_trc(dport->bfa, msg->state);
6587 	dport->i2hmsg.scn.state = msg->state;
6588 
6589 	switch (dport->i2hmsg.scn.state) {
6590 	case BFI_DPORT_SCN_TESTCOMP:
6591 		dport->result.end_time = bfa_get_log_time();
6592 		bfa_trc(dport->bfa, dport->result.end_time);
6593 
6594 		dport->result.status = msg->info.testcomp.status;
6595 		bfa_trc(dport->bfa, dport->result.status);
6596 
6597 		dport->result.roundtrip_latency =
6598 			cpu_to_be32(msg->info.testcomp.latency);
6599 		dport->result.est_cable_distance =
6600 			cpu_to_be32(msg->info.testcomp.distance);
6601 		dport->result.buffer_required =
6602 			be16_to_cpu(msg->info.testcomp.numbuffer);
6603 
6604 		dport->result.frmsz = be16_to_cpu(msg->info.testcomp.frm_sz);
6605 		dport->result.speed = msg->info.testcomp.speed;
6606 
6607 		bfa_trc(dport->bfa, dport->result.roundtrip_latency);
6608 		bfa_trc(dport->bfa, dport->result.est_cable_distance);
6609 		bfa_trc(dport->bfa, dport->result.buffer_required);
6610 		bfa_trc(dport->bfa, dport->result.frmsz);
6611 		bfa_trc(dport->bfa, dport->result.speed);
6612 
6613 		for (i = DPORT_TEST_ELOOP; i < DPORT_TEST_MAX; i++) {
6614 			dport->result.subtest[i].status =
6615 				msg->info.testcomp.subtest_status[i];
6616 			bfa_trc(dport->bfa, dport->result.subtest[i].status);
6617 		}
6618 		break;
6619 
6620 	case BFI_DPORT_SCN_TESTSKIP:
6621 	case BFI_DPORT_SCN_DDPORT_ENABLE:
6622 		memset(&dport->result, 0,
6623 				sizeof(struct bfa_diag_dport_result_s));
6624 		break;
6625 
6626 	case BFI_DPORT_SCN_TESTSTART:
6627 		memset(&dport->result, 0,
6628 				sizeof(struct bfa_diag_dport_result_s));
6629 		dport->rp_pwwn = msg->info.teststart.pwwn;
6630 		dport->rp_nwwn = msg->info.teststart.nwwn;
6631 		dport->lpcnt = cpu_to_be32(msg->info.teststart.numfrm);
6632 		bfa_dport_result_start(dport, msg->info.teststart.mode);
6633 		break;
6634 
6635 	case BFI_DPORT_SCN_SUBTESTSTART:
6636 		subtesttype = msg->info.teststart.type;
6637 		dport->result.subtest[subtesttype].start_time =
6638 			bfa_get_log_time();
6639 		dport->result.subtest[subtesttype].status =
6640 			DPORT_TEST_ST_INPRG;
6641 
6642 		bfa_trc(dport->bfa, subtesttype);
6643 		bfa_trc(dport->bfa,
6644 			dport->result.subtest[subtesttype].start_time);
6645 		break;
6646 
6647 	case BFI_DPORT_SCN_SFP_REMOVED:
6648 	case BFI_DPORT_SCN_DDPORT_DISABLED:
6649 	case BFI_DPORT_SCN_DDPORT_DISABLE:
6650 	case BFI_DPORT_SCN_FCPORT_DISABLE:
6651 		dport->result.status = DPORT_TEST_ST_IDLE;
6652 		break;
6653 
6654 	default:
6655 		bfa_sm_fault(dport->bfa, msg->state);
6656 	}
6657 
6658 	bfa_sm_send_event(dport, BFA_DPORT_SM_SCN);
6659 }
6660 
6661 /*
6662  * Dport enable
6663  *
6664  * @param[in] *bfa            - bfa data struct
6665  */
6666 bfa_status_t
6667 bfa_dport_enable(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6668 				bfa_cb_diag_t cbfn, void *cbarg)
6669 {
6670 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6671 	struct bfa_dport_s  *dport = &fcdiag->dport;
6672 
6673 	/*
6674 	 * Dport is not support in MEZZ card
6675 	 */
6676 	if (bfa_mfg_is_mezz(dport->bfa->ioc.attr->card_type)) {
6677 		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6678 		return BFA_STATUS_CMD_NOTSUPP_MEZZ;
6679 	}
6680 
6681 	/*
6682 	 * Dport is supported in CT2 or above
6683 	 */
6684 	if (!(bfa_asic_id_ct2(dport->bfa->ioc.pcidev.device_id))) {
6685 		bfa_trc(dport->bfa, dport->bfa->ioc.pcidev.device_id);
6686 		return BFA_STATUS_FEATURE_NOT_SUPPORTED;
6687 	}
6688 
6689 	/*
6690 	 * Check to see if IOC is down
6691 	*/
6692 	if (!bfa_iocfc_is_operational(bfa))
6693 		return BFA_STATUS_IOC_NON_OP;
6694 
6695 	/* if port is PBC disabled, return error */
6696 	if (bfa_fcport_is_pbcdisabled(bfa)) {
6697 		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6698 		return BFA_STATUS_PBC;
6699 	}
6700 
6701 	/*
6702 	 * Check if port mode is FC port
6703 	 */
6704 	if (bfa_ioc_get_type(&bfa->ioc) != BFA_IOC_TYPE_FC) {
6705 		bfa_trc(dport->bfa, bfa_ioc_get_type(&bfa->ioc));
6706 		return BFA_STATUS_CMD_NOTSUPP_CNA;
6707 	}
6708 
6709 	/*
6710 	 * Check if port is in LOOP mode
6711 	 */
6712 	if ((bfa_fcport_get_cfg_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP) ||
6713 	    (bfa_fcport_get_topology(bfa) == BFA_PORT_TOPOLOGY_LOOP)) {
6714 		bfa_trc(dport->bfa, 0);
6715 		return BFA_STATUS_TOPOLOGY_LOOP;
6716 	}
6717 
6718 	/*
6719 	 * Check if port is TRUNK mode
6720 	 */
6721 	if (bfa_fcport_is_trunk_enabled(bfa)) {
6722 		bfa_trc(dport->bfa, 0);
6723 		return BFA_STATUS_ERROR_TRUNK_ENABLED;
6724 	}
6725 
6726 	/*
6727 	 * Check if diag loopback is running
6728 	 */
6729 	if (bfa_fcdiag_lb_is_running(bfa)) {
6730 		bfa_trc(dport->bfa, 0);
6731 		return BFA_STATUS_DIAG_BUSY;
6732 	}
6733 
6734 	/*
6735 	 * Check to see if port is disable or in dport state
6736 	 */
6737 	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6738 	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6739 		bfa_trc(dport->bfa, 0);
6740 		return BFA_STATUS_PORT_NOT_DISABLED;
6741 	}
6742 
6743 	/*
6744 	 * Check if dport is in dynamic mode
6745 	 */
6746 	if (dport->dynamic)
6747 		return BFA_STATUS_DDPORT_ERR;
6748 
6749 	/*
6750 	 * Check if dport is busy
6751 	 */
6752 	if (bfa_dport_is_sending_req(dport))
6753 		return BFA_STATUS_DEVBUSY;
6754 
6755 	/*
6756 	 * Check if dport is already enabled
6757 	 */
6758 	if (bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6759 		bfa_trc(dport->bfa, 0);
6760 		return BFA_STATUS_DPORT_ENABLED;
6761 	}
6762 
6763 	bfa_trc(dport->bfa, lpcnt);
6764 	bfa_trc(dport->bfa, pat);
6765 	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6766 	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6767 	dport->cbfn = cbfn;
6768 	dport->cbarg = cbarg;
6769 
6770 	bfa_sm_send_event(dport, BFA_DPORT_SM_ENABLE);
6771 	return BFA_STATUS_OK;
6772 }
6773 
6774 /*
6775  *	Dport disable
6776  *
6777  *	@param[in] *bfa            - bfa data struct
6778  */
6779 bfa_status_t
6780 bfa_dport_disable(struct bfa_s *bfa, bfa_cb_diag_t cbfn, void *cbarg)
6781 {
6782 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6783 	struct bfa_dport_s *dport = &fcdiag->dport;
6784 
6785 	if (bfa_ioc_is_disabled(&bfa->ioc))
6786 		return BFA_STATUS_IOC_DISABLED;
6787 
6788 	/* if port is PBC disabled, return error */
6789 	if (bfa_fcport_is_pbcdisabled(bfa)) {
6790 		bfa_trc(dport->bfa, BFA_STATUS_PBC);
6791 		return BFA_STATUS_PBC;
6792 	}
6793 
6794 	/*
6795 	 * Check if dport is in dynamic mode
6796 	 */
6797 	if (dport->dynamic) {
6798 		return BFA_STATUS_DDPORT_ERR;
6799 	}
6800 
6801 	/*
6802 	 * Check to see if port is disable or in dport state
6803 	 */
6804 	if ((bfa_fcport_is_disabled(bfa) == BFA_FALSE) &&
6805 	    (bfa_fcport_is_dport(bfa) == BFA_FALSE)) {
6806 		bfa_trc(dport->bfa, 0);
6807 		return BFA_STATUS_PORT_NOT_DISABLED;
6808 	}
6809 
6810 	/*
6811 	 * Check if dport is busy
6812 	 */
6813 	if (bfa_dport_is_sending_req(dport))
6814 		return BFA_STATUS_DEVBUSY;
6815 
6816 	/*
6817 	 * Check if dport is already disabled
6818 	 */
6819 	if (bfa_sm_cmp_state(dport, bfa_dport_sm_disabled)) {
6820 		bfa_trc(dport->bfa, 0);
6821 		return BFA_STATUS_DPORT_DISABLED;
6822 	}
6823 
6824 	dport->cbfn = cbfn;
6825 	dport->cbarg = cbarg;
6826 
6827 	bfa_sm_send_event(dport, BFA_DPORT_SM_DISABLE);
6828 	return BFA_STATUS_OK;
6829 }
6830 
6831 /*
6832  * Dport start -- restart dport test
6833  *
6834  *   @param[in] *bfa		- bfa data struct
6835  */
6836 bfa_status_t
6837 bfa_dport_start(struct bfa_s *bfa, u32 lpcnt, u32 pat,
6838 			bfa_cb_diag_t cbfn, void *cbarg)
6839 {
6840 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6841 	struct bfa_dport_s *dport = &fcdiag->dport;
6842 
6843 	/*
6844 	 * Check to see if IOC is down
6845 	 */
6846 	if (!bfa_iocfc_is_operational(bfa))
6847 		return BFA_STATUS_IOC_NON_OP;
6848 
6849 	/*
6850 	 * Check if dport is in dynamic mode
6851 	 */
6852 	if (dport->dynamic)
6853 		return BFA_STATUS_DDPORT_ERR;
6854 
6855 	/*
6856 	 * Check if dport is busy
6857 	 */
6858 	if (bfa_dport_is_sending_req(dport))
6859 		return BFA_STATUS_DEVBUSY;
6860 
6861 	/*
6862 	 * Check if dport is in enabled state.
6863 	 * Test can only be restart when previous test has completed
6864 	 */
6865 	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6866 		bfa_trc(dport->bfa, 0);
6867 		return BFA_STATUS_DPORT_DISABLED;
6868 
6869 	} else {
6870 		if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6871 			return BFA_STATUS_DPORT_INV_SFP;
6872 
6873 		if (dport->test_state == BFA_DPORT_ST_INP)
6874 			return BFA_STATUS_DEVBUSY;
6875 
6876 		WARN_ON(dport->test_state != BFA_DPORT_ST_COMP);
6877 	}
6878 
6879 	bfa_trc(dport->bfa, lpcnt);
6880 	bfa_trc(dport->bfa, pat);
6881 
6882 	dport->lpcnt = (lpcnt) ? lpcnt : DPORT_ENABLE_LOOPCNT_DEFAULT;
6883 	dport->payload = (pat) ? pat : LB_PATTERN_DEFAULT;
6884 
6885 	dport->cbfn = cbfn;
6886 	dport->cbarg = cbarg;
6887 
6888 	bfa_sm_send_event(dport, BFA_DPORT_SM_START);
6889 	return BFA_STATUS_OK;
6890 }
6891 
6892 /*
6893  * Dport show -- return dport test result
6894  *
6895  *   @param[in] *bfa		- bfa data struct
6896  */
6897 bfa_status_t
6898 bfa_dport_show(struct bfa_s *bfa, struct bfa_diag_dport_result_s *result)
6899 {
6900 	struct bfa_fcdiag_s *fcdiag = BFA_FCDIAG_MOD(bfa);
6901 	struct bfa_dport_s *dport = &fcdiag->dport;
6902 
6903 	/*
6904 	 * Check to see if IOC is down
6905 	 */
6906 	if (!bfa_iocfc_is_operational(bfa))
6907 		return BFA_STATUS_IOC_NON_OP;
6908 
6909 	/*
6910 	 * Check if dport is busy
6911 	 */
6912 	if (bfa_dport_is_sending_req(dport))
6913 		return BFA_STATUS_DEVBUSY;
6914 
6915 	/*
6916 	 * Check if dport is in enabled state.
6917 	 */
6918 	if (!bfa_sm_cmp_state(dport, bfa_dport_sm_enabled)) {
6919 		bfa_trc(dport->bfa, 0);
6920 		return BFA_STATUS_DPORT_DISABLED;
6921 
6922 	}
6923 
6924 	/*
6925 	 * Check if there is SFP
6926 	 */
6927 	if (dport->test_state == BFA_DPORT_ST_NO_SFP)
6928 		return BFA_STATUS_DPORT_INV_SFP;
6929 
6930 	memcpy(result, &dport->result, sizeof(struct bfa_diag_dport_result_s));
6931 
6932 	return BFA_STATUS_OK;
6933 }
6934