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