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