xref: /linux/drivers/scsi/bfa/bfa_ioc.c (revision 0d456bad36d42d16022be045c8a53ddbb59ee478)
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 "bfad_im.h"
20 #include "bfa_ioc.h"
21 #include "bfi_reg.h"
22 #include "bfa_defs.h"
23 #include "bfa_defs_svc.h"
24 
25 BFA_TRC_FILE(CNA, IOC);
26 
27 /*
28  * IOC local definitions
29  */
30 #define BFA_IOC_TOV		3000	/* msecs */
31 #define BFA_IOC_HWSEM_TOV	500	/* msecs */
32 #define BFA_IOC_HB_TOV		500	/* msecs */
33 #define BFA_IOC_TOV_RECOVER	 BFA_IOC_HB_TOV
34 #define BFA_IOC_POLL_TOV	BFA_TIMER_FREQ
35 
36 #define bfa_ioc_timer_start(__ioc)					\
37 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
38 			bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
39 #define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
40 
41 #define bfa_hb_timer_start(__ioc)					\
42 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer,		\
43 			bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
44 #define bfa_hb_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->hb_timer)
45 
46 #define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
47 
48 /*
49  * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
50  */
51 
52 #define bfa_ioc_firmware_lock(__ioc)			\
53 			((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
54 #define bfa_ioc_firmware_unlock(__ioc)			\
55 			((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
56 #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
57 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
58 #define bfa_ioc_notify_fail(__ioc)              \
59 			((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
60 #define bfa_ioc_sync_start(__ioc)               \
61 			((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
62 #define bfa_ioc_sync_join(__ioc)                \
63 			((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
64 #define bfa_ioc_sync_leave(__ioc)               \
65 			((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
66 #define bfa_ioc_sync_ack(__ioc)                 \
67 			((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
68 #define bfa_ioc_sync_complete(__ioc)            \
69 			((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
70 
71 #define bfa_ioc_mbox_cmd_pending(__ioc)		\
72 			(!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
73 			readl((__ioc)->ioc_regs.hfn_mbox_cmd))
74 
75 bfa_boolean_t bfa_auto_recover = BFA_TRUE;
76 
77 /*
78  * forward declarations
79  */
80 static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
81 static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
82 static void bfa_ioc_timeout(void *ioc);
83 static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);
84 static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
85 static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
86 static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
87 static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
88 static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
89 static void bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc);
90 static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
91 static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
92 				enum bfa_ioc_event_e event);
93 static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
94 static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
95 static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
96 static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
97 
98 /*
99  * IOC state machine definitions/declarations
100  */
101 enum ioc_event {
102 	IOC_E_RESET		= 1,	/*  IOC reset request		*/
103 	IOC_E_ENABLE		= 2,	/*  IOC enable request		*/
104 	IOC_E_DISABLE		= 3,	/*  IOC disable request	*/
105 	IOC_E_DETACH		= 4,	/*  driver detach cleanup	*/
106 	IOC_E_ENABLED		= 5,	/*  f/w enabled		*/
107 	IOC_E_FWRSP_GETATTR	= 6,	/*  IOC get attribute response	*/
108 	IOC_E_DISABLED		= 7,	/*  f/w disabled		*/
109 	IOC_E_PFFAILED		= 8,	/*  failure notice by iocpf sm	*/
110 	IOC_E_HBFAIL		= 9,	/*  heartbeat failure		*/
111 	IOC_E_HWERROR		= 10,	/*  hardware error interrupt	*/
112 	IOC_E_TIMEOUT		= 11,	/*  timeout			*/
113 	IOC_E_HWFAILED		= 12,	/*  PCI mapping failure notice	*/
114 };
115 
116 bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
117 bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
118 bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
119 bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
120 bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
121 bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
122 bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
123 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
124 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
125 bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc_s, enum ioc_event);
126 
127 static struct bfa_sm_table_s ioc_sm_table[] = {
128 	{BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
129 	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
130 	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
131 	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
132 	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
133 	{BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
134 	{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
135 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
136 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
137 	{BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
138 };
139 
140 /*
141  * IOCPF state machine definitions/declarations
142  */
143 
144 #define bfa_iocpf_timer_start(__ioc)					\
145 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
146 			bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
147 #define bfa_iocpf_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->ioc_timer)
148 
149 #define bfa_iocpf_poll_timer_start(__ioc)				\
150 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
151 			bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)
152 
153 #define bfa_sem_timer_start(__ioc)					\
154 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer,	\
155 			bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
156 #define bfa_sem_timer_stop(__ioc)	bfa_timer_stop(&(__ioc)->sem_timer)
157 
158 /*
159  * Forward declareations for iocpf state machine
160  */
161 static void bfa_iocpf_timeout(void *ioc_arg);
162 static void bfa_iocpf_sem_timeout(void *ioc_arg);
163 static void bfa_iocpf_poll_timeout(void *ioc_arg);
164 
165 /*
166  * IOCPF state machine events
167  */
168 enum iocpf_event {
169 	IOCPF_E_ENABLE		= 1,	/*  IOCPF enable request	*/
170 	IOCPF_E_DISABLE		= 2,	/*  IOCPF disable request	*/
171 	IOCPF_E_STOP		= 3,	/*  stop on driver detach	*/
172 	IOCPF_E_FWREADY		= 4,	/*  f/w initialization done	*/
173 	IOCPF_E_FWRSP_ENABLE	= 5,	/*  enable f/w response	*/
174 	IOCPF_E_FWRSP_DISABLE	= 6,	/*  disable f/w response	*/
175 	IOCPF_E_FAIL		= 7,	/*  failure notice by ioc sm	*/
176 	IOCPF_E_INITFAIL	= 8,	/*  init fail notice by ioc sm	*/
177 	IOCPF_E_GETATTRFAIL	= 9,	/*  init fail notice by ioc sm	*/
178 	IOCPF_E_SEMLOCKED	= 10,	/*  h/w semaphore is locked	*/
179 	IOCPF_E_TIMEOUT		= 11,	/*  f/w response timeout	*/
180 	IOCPF_E_SEM_ERROR	= 12,	/*  h/w sem mapping error	*/
181 };
182 
183 /*
184  * IOCPF states
185  */
186 enum bfa_iocpf_state {
187 	BFA_IOCPF_RESET		= 1,	/*  IOC is in reset state */
188 	BFA_IOCPF_SEMWAIT	= 2,	/*  Waiting for IOC h/w semaphore */
189 	BFA_IOCPF_HWINIT	= 3,	/*  IOC h/w is being initialized */
190 	BFA_IOCPF_READY		= 4,	/*  IOCPF is initialized */
191 	BFA_IOCPF_INITFAIL	= 5,	/*  IOCPF failed */
192 	BFA_IOCPF_FAIL		= 6,	/*  IOCPF failed */
193 	BFA_IOCPF_DISABLING	= 7,	/*  IOCPF is being disabled */
194 	BFA_IOCPF_DISABLED	= 8,	/*  IOCPF is disabled */
195 	BFA_IOCPF_FWMISMATCH	= 9,	/*  IOC f/w different from drivers */
196 };
197 
198 bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
199 bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
200 bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
201 bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
202 bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
203 bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
204 bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
205 bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s,
206 						enum iocpf_event);
207 bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
208 bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);
209 bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
210 bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
211 bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s,
212 						enum iocpf_event);
213 bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
214 
215 static struct bfa_sm_table_s iocpf_sm_table[] = {
216 	{BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
217 	{BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
218 	{BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
219 	{BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
220 	{BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
221 	{BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
222 	{BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
223 	{BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
224 	{BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
225 	{BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
226 	{BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
227 	{BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
228 	{BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
229 	{BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
230 };
231 
232 /*
233  * IOC State Machine
234  */
235 
236 /*
237  * Beginning state. IOC uninit state.
238  */
239 
240 static void
241 bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
242 {
243 }
244 
245 /*
246  * IOC is in uninit state.
247  */
248 static void
249 bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
250 {
251 	bfa_trc(ioc, event);
252 
253 	switch (event) {
254 	case IOC_E_RESET:
255 		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
256 		break;
257 
258 	default:
259 		bfa_sm_fault(ioc, event);
260 	}
261 }
262 /*
263  * Reset entry actions -- initialize state machine
264  */
265 static void
266 bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
267 {
268 	bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
269 }
270 
271 /*
272  * IOC is in reset state.
273  */
274 static void
275 bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
276 {
277 	bfa_trc(ioc, event);
278 
279 	switch (event) {
280 	case IOC_E_ENABLE:
281 		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
282 		break;
283 
284 	case IOC_E_DISABLE:
285 		bfa_ioc_disable_comp(ioc);
286 		break;
287 
288 	case IOC_E_DETACH:
289 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
290 		break;
291 
292 	default:
293 		bfa_sm_fault(ioc, event);
294 	}
295 }
296 
297 
298 static void
299 bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
300 {
301 	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
302 }
303 
304 /*
305  * Host IOC function is being enabled, awaiting response from firmware.
306  * Semaphore is acquired.
307  */
308 static void
309 bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
310 {
311 	bfa_trc(ioc, event);
312 
313 	switch (event) {
314 	case IOC_E_ENABLED:
315 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
316 		break;
317 
318 	case IOC_E_PFFAILED:
319 		/* !!! fall through !!! */
320 	case IOC_E_HWERROR:
321 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
322 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
323 		if (event != IOC_E_PFFAILED)
324 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
325 		break;
326 
327 	case IOC_E_HWFAILED:
328 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
329 		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
330 		break;
331 
332 	case IOC_E_DISABLE:
333 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
334 		break;
335 
336 	case IOC_E_DETACH:
337 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
338 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
339 		break;
340 
341 	case IOC_E_ENABLE:
342 		break;
343 
344 	default:
345 		bfa_sm_fault(ioc, event);
346 	}
347 }
348 
349 
350 static void
351 bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
352 {
353 	bfa_ioc_timer_start(ioc);
354 	bfa_ioc_send_getattr(ioc);
355 }
356 
357 /*
358  * IOC configuration in progress. Timer is active.
359  */
360 static void
361 bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
362 {
363 	bfa_trc(ioc, event);
364 
365 	switch (event) {
366 	case IOC_E_FWRSP_GETATTR:
367 		bfa_ioc_timer_stop(ioc);
368 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
369 		break;
370 
371 	case IOC_E_PFFAILED:
372 	case IOC_E_HWERROR:
373 		bfa_ioc_timer_stop(ioc);
374 		/* !!! fall through !!! */
375 	case IOC_E_TIMEOUT:
376 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
377 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
378 		if (event != IOC_E_PFFAILED)
379 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
380 		break;
381 
382 	case IOC_E_DISABLE:
383 		bfa_ioc_timer_stop(ioc);
384 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
385 		break;
386 
387 	case IOC_E_ENABLE:
388 		break;
389 
390 	default:
391 		bfa_sm_fault(ioc, event);
392 	}
393 }
394 
395 static void
396 bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
397 {
398 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
399 
400 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
401 	bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
402 	bfa_ioc_hb_monitor(ioc);
403 	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
404 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
405 }
406 
407 static void
408 bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
409 {
410 	bfa_trc(ioc, event);
411 
412 	switch (event) {
413 	case IOC_E_ENABLE:
414 		break;
415 
416 	case IOC_E_DISABLE:
417 		bfa_hb_timer_stop(ioc);
418 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
419 		break;
420 
421 	case IOC_E_PFFAILED:
422 	case IOC_E_HWERROR:
423 		bfa_hb_timer_stop(ioc);
424 		/* !!! fall through !!! */
425 	case IOC_E_HBFAIL:
426 		if (ioc->iocpf.auto_recover)
427 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
428 		else
429 			bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
430 
431 		bfa_ioc_fail_notify(ioc);
432 
433 		if (event != IOC_E_PFFAILED)
434 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
435 		break;
436 
437 	default:
438 		bfa_sm_fault(ioc, event);
439 	}
440 }
441 
442 
443 static void
444 bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
445 {
446 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
447 	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
448 	BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
449 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
450 }
451 
452 /*
453  * IOC is being disabled
454  */
455 static void
456 bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
457 {
458 	bfa_trc(ioc, event);
459 
460 	switch (event) {
461 	case IOC_E_DISABLED:
462 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
463 		break;
464 
465 	case IOC_E_HWERROR:
466 		/*
467 		 * No state change.  Will move to disabled state
468 		 * after iocpf sm completes failure processing and
469 		 * moves to disabled state.
470 		 */
471 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
472 		break;
473 
474 	case IOC_E_HWFAILED:
475 		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
476 		bfa_ioc_disable_comp(ioc);
477 		break;
478 
479 	default:
480 		bfa_sm_fault(ioc, event);
481 	}
482 }
483 
484 /*
485  * IOC disable completion entry.
486  */
487 static void
488 bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
489 {
490 	bfa_ioc_disable_comp(ioc);
491 }
492 
493 static void
494 bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
495 {
496 	bfa_trc(ioc, event);
497 
498 	switch (event) {
499 	case IOC_E_ENABLE:
500 		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
501 		break;
502 
503 	case IOC_E_DISABLE:
504 		ioc->cbfn->disable_cbfn(ioc->bfa);
505 		break;
506 
507 	case IOC_E_DETACH:
508 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
509 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
510 		break;
511 
512 	default:
513 		bfa_sm_fault(ioc, event);
514 	}
515 }
516 
517 
518 static void
519 bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
520 {
521 	bfa_trc(ioc, 0);
522 }
523 
524 /*
525  * Hardware initialization retry.
526  */
527 static void
528 bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
529 {
530 	bfa_trc(ioc, event);
531 
532 	switch (event) {
533 	case IOC_E_ENABLED:
534 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
535 		break;
536 
537 	case IOC_E_PFFAILED:
538 	case IOC_E_HWERROR:
539 		/*
540 		 * Initialization retry failed.
541 		 */
542 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
543 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
544 		if (event != IOC_E_PFFAILED)
545 			bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
546 		break;
547 
548 	case IOC_E_HWFAILED:
549 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
550 		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
551 		break;
552 
553 	case IOC_E_ENABLE:
554 		break;
555 
556 	case IOC_E_DISABLE:
557 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
558 		break;
559 
560 	case IOC_E_DETACH:
561 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
562 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
563 		break;
564 
565 	default:
566 		bfa_sm_fault(ioc, event);
567 	}
568 }
569 
570 
571 static void
572 bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
573 {
574 	bfa_trc(ioc, 0);
575 }
576 
577 /*
578  * IOC failure.
579  */
580 static void
581 bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
582 {
583 	bfa_trc(ioc, event);
584 
585 	switch (event) {
586 
587 	case IOC_E_ENABLE:
588 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
589 		break;
590 
591 	case IOC_E_DISABLE:
592 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
593 		break;
594 
595 	case IOC_E_DETACH:
596 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
597 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
598 		break;
599 
600 	case IOC_E_HWERROR:
601 	case IOC_E_HWFAILED:
602 		/*
603 		 * HB failure / HW error notification, ignore.
604 		 */
605 		break;
606 	default:
607 		bfa_sm_fault(ioc, event);
608 	}
609 }
610 
611 static void
612 bfa_ioc_sm_hwfail_entry(struct bfa_ioc_s *ioc)
613 {
614 	bfa_trc(ioc, 0);
615 }
616 
617 static void
618 bfa_ioc_sm_hwfail(struct bfa_ioc_s *ioc, enum ioc_event event)
619 {
620 	bfa_trc(ioc, event);
621 
622 	switch (event) {
623 	case IOC_E_ENABLE:
624 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
625 		break;
626 
627 	case IOC_E_DISABLE:
628 		ioc->cbfn->disable_cbfn(ioc->bfa);
629 		break;
630 
631 	case IOC_E_DETACH:
632 		bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
633 		break;
634 
635 	case IOC_E_HWERROR:
636 		/* Ignore - already in hwfail state */
637 		break;
638 
639 	default:
640 		bfa_sm_fault(ioc, event);
641 	}
642 }
643 
644 /*
645  * IOCPF State Machine
646  */
647 
648 /*
649  * Reset entry actions -- initialize state machine
650  */
651 static void
652 bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
653 {
654 	iocpf->fw_mismatch_notified = BFA_FALSE;
655 	iocpf->auto_recover = bfa_auto_recover;
656 }
657 
658 /*
659  * Beginning state. IOC is in reset state.
660  */
661 static void
662 bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
663 {
664 	struct bfa_ioc_s *ioc = iocpf->ioc;
665 
666 	bfa_trc(ioc, event);
667 
668 	switch (event) {
669 	case IOCPF_E_ENABLE:
670 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
671 		break;
672 
673 	case IOCPF_E_STOP:
674 		break;
675 
676 	default:
677 		bfa_sm_fault(ioc, event);
678 	}
679 }
680 
681 /*
682  * Semaphore should be acquired for version check.
683  */
684 static void
685 bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
686 {
687 	struct bfi_ioc_image_hdr_s	fwhdr;
688 	u32	r32, fwstate, pgnum, pgoff, loff = 0;
689 	int	i;
690 
691 	/*
692 	 * Spin on init semaphore to serialize.
693 	 */
694 	r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg);
695 	while (r32 & 0x1) {
696 		udelay(20);
697 		r32 = readl(iocpf->ioc->ioc_regs.ioc_init_sem_reg);
698 	}
699 
700 	/* h/w sem init */
701 	fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate);
702 	if (fwstate == BFI_IOC_UNINIT) {
703 		writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
704 		goto sem_get;
705 	}
706 
707 	bfa_ioc_fwver_get(iocpf->ioc, &fwhdr);
708 
709 	if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {
710 		writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
711 		goto sem_get;
712 	}
713 
714 	/*
715 	 * Clear fwver hdr
716 	 */
717 	pgnum = PSS_SMEM_PGNUM(iocpf->ioc->ioc_regs.smem_pg0, loff);
718 	pgoff = PSS_SMEM_PGOFF(loff);
719 	writel(pgnum, iocpf->ioc->ioc_regs.host_page_num_fn);
720 
721 	for (i = 0; i < sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32); i++) {
722 		bfa_mem_write(iocpf->ioc->ioc_regs.smem_page_start, loff, 0);
723 		loff += sizeof(u32);
724 	}
725 
726 	bfa_trc(iocpf->ioc, fwstate);
727 	bfa_trc(iocpf->ioc, swab32(fwhdr.exec));
728 	writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate);
729 	writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.alt_ioc_fwstate);
730 
731 	/*
732 	 * Unlock the hw semaphore. Should be here only once per boot.
733 	 */
734 	bfa_ioc_ownership_reset(iocpf->ioc);
735 
736 	/*
737 	 * unlock init semaphore.
738 	 */
739 	writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg);
740 
741 sem_get:
742 	bfa_ioc_hw_sem_get(iocpf->ioc);
743 }
744 
745 /*
746  * Awaiting h/w semaphore to continue with version check.
747  */
748 static void
749 bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
750 {
751 	struct bfa_ioc_s *ioc = iocpf->ioc;
752 
753 	bfa_trc(ioc, event);
754 
755 	switch (event) {
756 	case IOCPF_E_SEMLOCKED:
757 		if (bfa_ioc_firmware_lock(ioc)) {
758 			if (bfa_ioc_sync_start(ioc)) {
759 				bfa_ioc_sync_join(ioc);
760 				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
761 			} else {
762 				bfa_ioc_firmware_unlock(ioc);
763 				writel(1, ioc->ioc_regs.ioc_sem_reg);
764 				bfa_sem_timer_start(ioc);
765 			}
766 		} else {
767 			writel(1, ioc->ioc_regs.ioc_sem_reg);
768 			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
769 		}
770 		break;
771 
772 	case IOCPF_E_SEM_ERROR:
773 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
774 		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
775 		break;
776 
777 	case IOCPF_E_DISABLE:
778 		bfa_sem_timer_stop(ioc);
779 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
780 		bfa_fsm_send_event(ioc, IOC_E_DISABLED);
781 		break;
782 
783 	case IOCPF_E_STOP:
784 		bfa_sem_timer_stop(ioc);
785 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
786 		break;
787 
788 	default:
789 		bfa_sm_fault(ioc, event);
790 	}
791 }
792 
793 /*
794  * Notify enable completion callback.
795  */
796 static void
797 bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
798 {
799 	/*
800 	 * Call only the first time sm enters fwmismatch state.
801 	 */
802 	if (iocpf->fw_mismatch_notified == BFA_FALSE)
803 		bfa_ioc_pf_fwmismatch(iocpf->ioc);
804 
805 	iocpf->fw_mismatch_notified = BFA_TRUE;
806 	bfa_iocpf_timer_start(iocpf->ioc);
807 }
808 
809 /*
810  * Awaiting firmware version match.
811  */
812 static void
813 bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
814 {
815 	struct bfa_ioc_s *ioc = iocpf->ioc;
816 
817 	bfa_trc(ioc, event);
818 
819 	switch (event) {
820 	case IOCPF_E_TIMEOUT:
821 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
822 		break;
823 
824 	case IOCPF_E_DISABLE:
825 		bfa_iocpf_timer_stop(ioc);
826 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
827 		bfa_fsm_send_event(ioc, IOC_E_DISABLED);
828 		break;
829 
830 	case IOCPF_E_STOP:
831 		bfa_iocpf_timer_stop(ioc);
832 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
833 		break;
834 
835 	default:
836 		bfa_sm_fault(ioc, event);
837 	}
838 }
839 
840 /*
841  * Request for semaphore.
842  */
843 static void
844 bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
845 {
846 	bfa_ioc_hw_sem_get(iocpf->ioc);
847 }
848 
849 /*
850  * Awaiting semaphore for h/w initialzation.
851  */
852 static void
853 bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
854 {
855 	struct bfa_ioc_s *ioc = iocpf->ioc;
856 
857 	bfa_trc(ioc, event);
858 
859 	switch (event) {
860 	case IOCPF_E_SEMLOCKED:
861 		if (bfa_ioc_sync_complete(ioc)) {
862 			bfa_ioc_sync_join(ioc);
863 			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
864 		} else {
865 			writel(1, ioc->ioc_regs.ioc_sem_reg);
866 			bfa_sem_timer_start(ioc);
867 		}
868 		break;
869 
870 	case IOCPF_E_SEM_ERROR:
871 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
872 		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
873 		break;
874 
875 	case IOCPF_E_DISABLE:
876 		bfa_sem_timer_stop(ioc);
877 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
878 		break;
879 
880 	default:
881 		bfa_sm_fault(ioc, event);
882 	}
883 }
884 
885 static void
886 bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
887 {
888 	iocpf->poll_time = 0;
889 	bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
890 }
891 
892 /*
893  * Hardware is being initialized. Interrupts are enabled.
894  * Holding hardware semaphore lock.
895  */
896 static void
897 bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
898 {
899 	struct bfa_ioc_s *ioc = iocpf->ioc;
900 
901 	bfa_trc(ioc, event);
902 
903 	switch (event) {
904 	case IOCPF_E_FWREADY:
905 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
906 		break;
907 
908 	case IOCPF_E_TIMEOUT:
909 		writel(1, ioc->ioc_regs.ioc_sem_reg);
910 		bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
911 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
912 		break;
913 
914 	case IOCPF_E_DISABLE:
915 		bfa_iocpf_timer_stop(ioc);
916 		bfa_ioc_sync_leave(ioc);
917 		writel(1, ioc->ioc_regs.ioc_sem_reg);
918 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
919 		break;
920 
921 	default:
922 		bfa_sm_fault(ioc, event);
923 	}
924 }
925 
926 static void
927 bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
928 {
929 	bfa_iocpf_timer_start(iocpf->ioc);
930 	/*
931 	 * Enable Interrupts before sending fw IOC ENABLE cmd.
932 	 */
933 	iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
934 	bfa_ioc_send_enable(iocpf->ioc);
935 }
936 
937 /*
938  * Host IOC function is being enabled, awaiting response from firmware.
939  * Semaphore is acquired.
940  */
941 static void
942 bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
943 {
944 	struct bfa_ioc_s *ioc = iocpf->ioc;
945 
946 	bfa_trc(ioc, event);
947 
948 	switch (event) {
949 	case IOCPF_E_FWRSP_ENABLE:
950 		bfa_iocpf_timer_stop(ioc);
951 		writel(1, ioc->ioc_regs.ioc_sem_reg);
952 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
953 		break;
954 
955 	case IOCPF_E_INITFAIL:
956 		bfa_iocpf_timer_stop(ioc);
957 		/*
958 		 * !!! fall through !!!
959 		 */
960 
961 	case IOCPF_E_TIMEOUT:
962 		writel(1, ioc->ioc_regs.ioc_sem_reg);
963 		if (event == IOCPF_E_TIMEOUT)
964 			bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
965 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
966 		break;
967 
968 	case IOCPF_E_DISABLE:
969 		bfa_iocpf_timer_stop(ioc);
970 		writel(1, ioc->ioc_regs.ioc_sem_reg);
971 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
972 		break;
973 
974 	default:
975 		bfa_sm_fault(ioc, event);
976 	}
977 }
978 
979 static void
980 bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
981 {
982 	bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
983 }
984 
985 static void
986 bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
987 {
988 	struct bfa_ioc_s *ioc = iocpf->ioc;
989 
990 	bfa_trc(ioc, event);
991 
992 	switch (event) {
993 	case IOCPF_E_DISABLE:
994 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
995 		break;
996 
997 	case IOCPF_E_GETATTRFAIL:
998 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
999 		break;
1000 
1001 	case IOCPF_E_FAIL:
1002 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
1003 		break;
1004 
1005 	default:
1006 		bfa_sm_fault(ioc, event);
1007 	}
1008 }
1009 
1010 static void
1011 bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
1012 {
1013 	bfa_iocpf_timer_start(iocpf->ioc);
1014 	bfa_ioc_send_disable(iocpf->ioc);
1015 }
1016 
1017 /*
1018  * IOC is being disabled
1019  */
1020 static void
1021 bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1022 {
1023 	struct bfa_ioc_s *ioc = iocpf->ioc;
1024 
1025 	bfa_trc(ioc, event);
1026 
1027 	switch (event) {
1028 	case IOCPF_E_FWRSP_DISABLE:
1029 		bfa_iocpf_timer_stop(ioc);
1030 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1031 		break;
1032 
1033 	case IOCPF_E_FAIL:
1034 		bfa_iocpf_timer_stop(ioc);
1035 		/*
1036 		 * !!! fall through !!!
1037 		 */
1038 
1039 	case IOCPF_E_TIMEOUT:
1040 		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1041 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1042 		break;
1043 
1044 	case IOCPF_E_FWRSP_ENABLE:
1045 		break;
1046 
1047 	default:
1048 		bfa_sm_fault(ioc, event);
1049 	}
1050 }
1051 
1052 static void
1053 bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf)
1054 {
1055 	bfa_ioc_hw_sem_get(iocpf->ioc);
1056 }
1057 
1058 /*
1059  * IOC hb ack request is being removed.
1060  */
1061 static void
1062 bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1063 {
1064 	struct bfa_ioc_s *ioc = iocpf->ioc;
1065 
1066 	bfa_trc(ioc, event);
1067 
1068 	switch (event) {
1069 	case IOCPF_E_SEMLOCKED:
1070 		bfa_ioc_sync_leave(ioc);
1071 		writel(1, ioc->ioc_regs.ioc_sem_reg);
1072 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1073 		break;
1074 
1075 	case IOCPF_E_SEM_ERROR:
1076 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1077 		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1078 		break;
1079 
1080 	case IOCPF_E_FAIL:
1081 		break;
1082 
1083 	default:
1084 		bfa_sm_fault(ioc, event);
1085 	}
1086 }
1087 
1088 /*
1089  * IOC disable completion entry.
1090  */
1091 static void
1092 bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
1093 {
1094 	bfa_ioc_mbox_flush(iocpf->ioc);
1095 	bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
1096 }
1097 
1098 static void
1099 bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1100 {
1101 	struct bfa_ioc_s *ioc = iocpf->ioc;
1102 
1103 	bfa_trc(ioc, event);
1104 
1105 	switch (event) {
1106 	case IOCPF_E_ENABLE:
1107 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1108 		break;
1109 
1110 	case IOCPF_E_STOP:
1111 		bfa_ioc_firmware_unlock(ioc);
1112 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1113 		break;
1114 
1115 	default:
1116 		bfa_sm_fault(ioc, event);
1117 	}
1118 }
1119 
1120 static void
1121 bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
1122 {
1123 	bfa_ioc_debug_save_ftrc(iocpf->ioc);
1124 	bfa_ioc_hw_sem_get(iocpf->ioc);
1125 }
1126 
1127 /*
1128  * Hardware initialization failed.
1129  */
1130 static void
1131 bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1132 {
1133 	struct bfa_ioc_s *ioc = iocpf->ioc;
1134 
1135 	bfa_trc(ioc, event);
1136 
1137 	switch (event) {
1138 	case IOCPF_E_SEMLOCKED:
1139 		bfa_ioc_notify_fail(ioc);
1140 		bfa_ioc_sync_leave(ioc);
1141 		writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1142 		writel(1, ioc->ioc_regs.ioc_sem_reg);
1143 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
1144 		break;
1145 
1146 	case IOCPF_E_SEM_ERROR:
1147 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1148 		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1149 		break;
1150 
1151 	case IOCPF_E_DISABLE:
1152 		bfa_sem_timer_stop(ioc);
1153 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1154 		break;
1155 
1156 	case IOCPF_E_STOP:
1157 		bfa_sem_timer_stop(ioc);
1158 		bfa_ioc_firmware_unlock(ioc);
1159 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1160 		break;
1161 
1162 	case IOCPF_E_FAIL:
1163 		break;
1164 
1165 	default:
1166 		bfa_sm_fault(ioc, event);
1167 	}
1168 }
1169 
1170 static void
1171 bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
1172 {
1173 	bfa_trc(iocpf->ioc, 0);
1174 }
1175 
1176 /*
1177  * Hardware initialization failed.
1178  */
1179 static void
1180 bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1181 {
1182 	struct bfa_ioc_s *ioc = iocpf->ioc;
1183 
1184 	bfa_trc(ioc, event);
1185 
1186 	switch (event) {
1187 	case IOCPF_E_DISABLE:
1188 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1189 		break;
1190 
1191 	case IOCPF_E_STOP:
1192 		bfa_ioc_firmware_unlock(ioc);
1193 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1194 		break;
1195 
1196 	default:
1197 		bfa_sm_fault(ioc, event);
1198 	}
1199 }
1200 
1201 static void
1202 bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
1203 {
1204 	/*
1205 	 * Mark IOC as failed in hardware and stop firmware.
1206 	 */
1207 	bfa_ioc_lpu_stop(iocpf->ioc);
1208 
1209 	/*
1210 	 * Flush any queued up mailbox requests.
1211 	 */
1212 	bfa_ioc_mbox_flush(iocpf->ioc);
1213 
1214 	bfa_ioc_hw_sem_get(iocpf->ioc);
1215 }
1216 
1217 static void
1218 bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1219 {
1220 	struct bfa_ioc_s *ioc = iocpf->ioc;
1221 
1222 	bfa_trc(ioc, event);
1223 
1224 	switch (event) {
1225 	case IOCPF_E_SEMLOCKED:
1226 		bfa_ioc_sync_ack(ioc);
1227 		bfa_ioc_notify_fail(ioc);
1228 		if (!iocpf->auto_recover) {
1229 			bfa_ioc_sync_leave(ioc);
1230 			writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1231 			writel(1, ioc->ioc_regs.ioc_sem_reg);
1232 			bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1233 		} else {
1234 			if (bfa_ioc_sync_complete(ioc))
1235 				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
1236 			else {
1237 				writel(1, ioc->ioc_regs.ioc_sem_reg);
1238 				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1239 			}
1240 		}
1241 		break;
1242 
1243 	case IOCPF_E_SEM_ERROR:
1244 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1245 		bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1246 		break;
1247 
1248 	case IOCPF_E_DISABLE:
1249 		bfa_sem_timer_stop(ioc);
1250 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1251 		break;
1252 
1253 	case IOCPF_E_FAIL:
1254 		break;
1255 
1256 	default:
1257 		bfa_sm_fault(ioc, event);
1258 	}
1259 }
1260 
1261 static void
1262 bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
1263 {
1264 	bfa_trc(iocpf->ioc, 0);
1265 }
1266 
1267 /*
1268  * IOC is in failed state.
1269  */
1270 static void
1271 bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1272 {
1273 	struct bfa_ioc_s *ioc = iocpf->ioc;
1274 
1275 	bfa_trc(ioc, event);
1276 
1277 	switch (event) {
1278 	case IOCPF_E_DISABLE:
1279 		bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1280 		break;
1281 
1282 	default:
1283 		bfa_sm_fault(ioc, event);
1284 	}
1285 }
1286 
1287 /*
1288  *  BFA IOC private functions
1289  */
1290 
1291 /*
1292  * Notify common modules registered for notification.
1293  */
1294 static void
1295 bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)
1296 {
1297 	struct bfa_ioc_notify_s	*notify;
1298 	struct list_head	*qe;
1299 
1300 	list_for_each(qe, &ioc->notify_q) {
1301 		notify = (struct bfa_ioc_notify_s *)qe;
1302 		notify->cbfn(notify->cbarg, event);
1303 	}
1304 }
1305 
1306 static void
1307 bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
1308 {
1309 	ioc->cbfn->disable_cbfn(ioc->bfa);
1310 	bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
1311 }
1312 
1313 bfa_boolean_t
1314 bfa_ioc_sem_get(void __iomem *sem_reg)
1315 {
1316 	u32 r32;
1317 	int cnt = 0;
1318 #define BFA_SEM_SPINCNT	3000
1319 
1320 	r32 = readl(sem_reg);
1321 
1322 	while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
1323 		cnt++;
1324 		udelay(2);
1325 		r32 = readl(sem_reg);
1326 	}
1327 
1328 	if (!(r32 & 1))
1329 		return BFA_TRUE;
1330 
1331 	return BFA_FALSE;
1332 }
1333 
1334 static void
1335 bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
1336 {
1337 	u32	r32;
1338 
1339 	/*
1340 	 * First read to the semaphore register will return 0, subsequent reads
1341 	 * will return 1. Semaphore is released by writing 1 to the register
1342 	 */
1343 	r32 = readl(ioc->ioc_regs.ioc_sem_reg);
1344 	if (r32 == ~0) {
1345 		WARN_ON(r32 == ~0);
1346 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
1347 		return;
1348 	}
1349 	if (!(r32 & 1)) {
1350 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
1351 		return;
1352 	}
1353 
1354 	bfa_sem_timer_start(ioc);
1355 }
1356 
1357 /*
1358  * Initialize LPU local memory (aka secondary memory / SRAM)
1359  */
1360 static void
1361 bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
1362 {
1363 	u32	pss_ctl;
1364 	int		i;
1365 #define PSS_LMEM_INIT_TIME  10000
1366 
1367 	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1368 	pss_ctl &= ~__PSS_LMEM_RESET;
1369 	pss_ctl |= __PSS_LMEM_INIT_EN;
1370 
1371 	/*
1372 	 * i2c workaround 12.5khz clock
1373 	 */
1374 	pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
1375 	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1376 
1377 	/*
1378 	 * wait for memory initialization to be complete
1379 	 */
1380 	i = 0;
1381 	do {
1382 		pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1383 		i++;
1384 	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1385 
1386 	/*
1387 	 * If memory initialization is not successful, IOC timeout will catch
1388 	 * such failures.
1389 	 */
1390 	WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
1391 	bfa_trc(ioc, pss_ctl);
1392 
1393 	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
1394 	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1395 }
1396 
1397 static void
1398 bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
1399 {
1400 	u32	pss_ctl;
1401 
1402 	/*
1403 	 * Take processor out of reset.
1404 	 */
1405 	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1406 	pss_ctl &= ~__PSS_LPU0_RESET;
1407 
1408 	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1409 }
1410 
1411 static void
1412 bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
1413 {
1414 	u32	pss_ctl;
1415 
1416 	/*
1417 	 * Put processors in reset.
1418 	 */
1419 	pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1420 	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1421 
1422 	writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1423 }
1424 
1425 /*
1426  * Get driver and firmware versions.
1427  */
1428 void
1429 bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1430 {
1431 	u32	pgnum, pgoff;
1432 	u32	loff = 0;
1433 	int		i;
1434 	u32	*fwsig = (u32 *) fwhdr;
1435 
1436 	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1437 	pgoff = PSS_SMEM_PGOFF(loff);
1438 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1439 
1440 	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
1441 	     i++) {
1442 		fwsig[i] =
1443 			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
1444 		loff += sizeof(u32);
1445 	}
1446 }
1447 
1448 /*
1449  * Returns TRUE if same.
1450  */
1451 bfa_boolean_t
1452 bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1453 {
1454 	struct bfi_ioc_image_hdr_s *drv_fwhdr;
1455 	int i;
1456 
1457 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1458 		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1459 
1460 	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1461 		if (fwhdr->md5sum[i] != cpu_to_le32(drv_fwhdr->md5sum[i])) {
1462 			bfa_trc(ioc, i);
1463 			bfa_trc(ioc, fwhdr->md5sum[i]);
1464 			bfa_trc(ioc, drv_fwhdr->md5sum[i]);
1465 			return BFA_FALSE;
1466 		}
1467 	}
1468 
1469 	bfa_trc(ioc, fwhdr->md5sum[0]);
1470 	return BFA_TRUE;
1471 }
1472 
1473 /*
1474  * Return true if current running version is valid. Firmware signature and
1475  * execution context (driver/bios) must match.
1476  */
1477 static bfa_boolean_t
1478 bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
1479 {
1480 	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
1481 
1482 	bfa_ioc_fwver_get(ioc, &fwhdr);
1483 	drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1484 		bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1485 
1486 	if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
1487 		bfa_trc(ioc, fwhdr.signature);
1488 		bfa_trc(ioc, drv_fwhdr->signature);
1489 		return BFA_FALSE;
1490 	}
1491 
1492 	if (swab32(fwhdr.bootenv) != boot_env) {
1493 		bfa_trc(ioc, fwhdr.bootenv);
1494 		bfa_trc(ioc, boot_env);
1495 		return BFA_FALSE;
1496 	}
1497 
1498 	return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1499 }
1500 
1501 /*
1502  * Conditionally flush any pending message from firmware at start.
1503  */
1504 static void
1505 bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1506 {
1507 	u32	r32;
1508 
1509 	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
1510 	if (r32)
1511 		writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1512 }
1513 
1514 static void
1515 bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1516 {
1517 	enum bfi_ioc_state ioc_fwstate;
1518 	bfa_boolean_t fwvalid;
1519 	u32 boot_type;
1520 	u32 boot_env;
1521 
1522 	ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
1523 
1524 	if (force)
1525 		ioc_fwstate = BFI_IOC_UNINIT;
1526 
1527 	bfa_trc(ioc, ioc_fwstate);
1528 
1529 	boot_type = BFI_FWBOOT_TYPE_NORMAL;
1530 	boot_env = BFI_FWBOOT_ENV_OS;
1531 
1532 	/*
1533 	 * check if firmware is valid
1534 	 */
1535 	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
1536 		BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
1537 
1538 	if (!fwvalid) {
1539 		bfa_ioc_boot(ioc, boot_type, boot_env);
1540 		bfa_ioc_poll_fwinit(ioc);
1541 		return;
1542 	}
1543 
1544 	/*
1545 	 * If hardware initialization is in progress (initialized by other IOC),
1546 	 * just wait for an initialization completion interrupt.
1547 	 */
1548 	if (ioc_fwstate == BFI_IOC_INITING) {
1549 		bfa_ioc_poll_fwinit(ioc);
1550 		return;
1551 	}
1552 
1553 	/*
1554 	 * If IOC function is disabled and firmware version is same,
1555 	 * just re-enable IOC.
1556 	 *
1557 	 * If option rom, IOC must not be in operational state. With
1558 	 * convergence, IOC will be in operational state when 2nd driver
1559 	 * is loaded.
1560 	 */
1561 	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
1562 
1563 		/*
1564 		 * When using MSI-X any pending firmware ready event should
1565 		 * be flushed. Otherwise MSI-X interrupts are not delivered.
1566 		 */
1567 		bfa_ioc_msgflush(ioc);
1568 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
1569 		return;
1570 	}
1571 
1572 	/*
1573 	 * Initialize the h/w for any other states.
1574 	 */
1575 	bfa_ioc_boot(ioc, boot_type, boot_env);
1576 	bfa_ioc_poll_fwinit(ioc);
1577 }
1578 
1579 static void
1580 bfa_ioc_timeout(void *ioc_arg)
1581 {
1582 	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
1583 
1584 	bfa_trc(ioc, 0);
1585 	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1586 }
1587 
1588 void
1589 bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1590 {
1591 	u32 *msgp = (u32 *) ioc_msg;
1592 	u32 i;
1593 
1594 	bfa_trc(ioc, msgp[0]);
1595 	bfa_trc(ioc, len);
1596 
1597 	WARN_ON(len > BFI_IOC_MSGLEN_MAX);
1598 
1599 	/*
1600 	 * first write msg to mailbox registers
1601 	 */
1602 	for (i = 0; i < len / sizeof(u32); i++)
1603 		writel(cpu_to_le32(msgp[i]),
1604 			ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
1605 
1606 	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
1607 		writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
1608 
1609 	/*
1610 	 * write 1 to mailbox CMD to trigger LPU event
1611 	 */
1612 	writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1613 	(void) readl(ioc->ioc_regs.hfn_mbox_cmd);
1614 }
1615 
1616 static void
1617 bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1618 {
1619 	struct bfi_ioc_ctrl_req_s enable_req;
1620 	struct timeval tv;
1621 
1622 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1623 		    bfa_ioc_portid(ioc));
1624 	enable_req.clscode = cpu_to_be16(ioc->clscode);
1625 	do_gettimeofday(&tv);
1626 	enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
1627 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1628 }
1629 
1630 static void
1631 bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1632 {
1633 	struct bfi_ioc_ctrl_req_s disable_req;
1634 
1635 	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1636 		    bfa_ioc_portid(ioc));
1637 	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1638 }
1639 
1640 static void
1641 bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1642 {
1643 	struct bfi_ioc_getattr_req_s	attr_req;
1644 
1645 	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1646 		    bfa_ioc_portid(ioc));
1647 	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1648 	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1649 }
1650 
1651 static void
1652 bfa_ioc_hb_check(void *cbarg)
1653 {
1654 	struct bfa_ioc_s  *ioc = cbarg;
1655 	u32	hb_count;
1656 
1657 	hb_count = readl(ioc->ioc_regs.heartbeat);
1658 	if (ioc->hb_count == hb_count) {
1659 		bfa_ioc_recover(ioc);
1660 		return;
1661 	} else {
1662 		ioc->hb_count = hb_count;
1663 	}
1664 
1665 	bfa_ioc_mbox_poll(ioc);
1666 	bfa_hb_timer_start(ioc);
1667 }
1668 
1669 static void
1670 bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1671 {
1672 	ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
1673 	bfa_hb_timer_start(ioc);
1674 }
1675 
1676 /*
1677  *	Initiate a full firmware download.
1678  */
1679 static void
1680 bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1681 		    u32 boot_env)
1682 {
1683 	u32 *fwimg;
1684 	u32 pgnum, pgoff;
1685 	u32 loff = 0;
1686 	u32 chunkno = 0;
1687 	u32 i;
1688 	u32 asicmode;
1689 
1690 	bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
1691 	fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
1692 
1693 	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1694 	pgoff = PSS_SMEM_PGOFF(loff);
1695 
1696 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1697 
1698 	for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
1699 
1700 		if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1701 			chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
1702 			fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
1703 					BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
1704 		}
1705 
1706 		/*
1707 		 * write smem
1708 		 */
1709 		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
1710 			cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]));
1711 
1712 		loff += sizeof(u32);
1713 
1714 		/*
1715 		 * handle page offset wrap around
1716 		 */
1717 		loff = PSS_SMEM_PGOFF(loff);
1718 		if (loff == 0) {
1719 			pgnum++;
1720 			writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1721 		}
1722 	}
1723 
1724 	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1725 			ioc->ioc_regs.host_page_num_fn);
1726 
1727 	/*
1728 	 * Set boot type and device mode at the end.
1729 	 */
1730 	asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
1731 				ioc->port0_mode, ioc->port1_mode);
1732 	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
1733 			swab32(asicmode));
1734 	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,
1735 			swab32(boot_type));
1736 	bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
1737 			swab32(boot_env));
1738 }
1739 
1740 
1741 /*
1742  * Update BFA configuration from firmware configuration.
1743  */
1744 static void
1745 bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1746 {
1747 	struct bfi_ioc_attr_s	*attr = ioc->attr;
1748 
1749 	attr->adapter_prop  = be32_to_cpu(attr->adapter_prop);
1750 	attr->card_type     = be32_to_cpu(attr->card_type);
1751 	attr->maxfrsize	    = be16_to_cpu(attr->maxfrsize);
1752 	ioc->fcmode	= (attr->port_mode == BFI_PORT_MODE_FC);
1753 	attr->mfg_year	= be16_to_cpu(attr->mfg_year);
1754 
1755 	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1756 }
1757 
1758 /*
1759  * Attach time initialization of mbox logic.
1760  */
1761 static void
1762 bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1763 {
1764 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
1765 	int	mc;
1766 
1767 	INIT_LIST_HEAD(&mod->cmd_q);
1768 	for (mc = 0; mc < BFI_MC_MAX; mc++) {
1769 		mod->mbhdlr[mc].cbfn = NULL;
1770 		mod->mbhdlr[mc].cbarg = ioc->bfa;
1771 	}
1772 }
1773 
1774 /*
1775  * Mbox poll timer -- restarts any pending mailbox requests.
1776  */
1777 static void
1778 bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1779 {
1780 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
1781 	struct bfa_mbox_cmd_s		*cmd;
1782 	u32			stat;
1783 
1784 	/*
1785 	 * If no command pending, do nothing
1786 	 */
1787 	if (list_empty(&mod->cmd_q))
1788 		return;
1789 
1790 	/*
1791 	 * If previous command is not yet fetched by firmware, do nothing
1792 	 */
1793 	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
1794 	if (stat)
1795 		return;
1796 
1797 	/*
1798 	 * Enqueue command to firmware.
1799 	 */
1800 	bfa_q_deq(&mod->cmd_q, &cmd);
1801 	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1802 }
1803 
1804 /*
1805  * Cleanup any pending requests.
1806  */
1807 static void
1808 bfa_ioc_mbox_flush(struct bfa_ioc_s *ioc)
1809 {
1810 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
1811 	struct bfa_mbox_cmd_s		*cmd;
1812 
1813 	while (!list_empty(&mod->cmd_q))
1814 		bfa_q_deq(&mod->cmd_q, &cmd);
1815 }
1816 
1817 /*
1818  * Read data from SMEM to host through PCI memmap
1819  *
1820  * @param[in]	ioc	memory for IOC
1821  * @param[in]	tbuf	app memory to store data from smem
1822  * @param[in]	soff	smem offset
1823  * @param[in]	sz	size of smem in bytes
1824  */
1825 static bfa_status_t
1826 bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
1827 {
1828 	u32 pgnum, loff;
1829 	__be32 r32;
1830 	int i, len;
1831 	u32 *buf = tbuf;
1832 
1833 	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1834 	loff = PSS_SMEM_PGOFF(soff);
1835 	bfa_trc(ioc, pgnum);
1836 	bfa_trc(ioc, loff);
1837 	bfa_trc(ioc, sz);
1838 
1839 	/*
1840 	 *  Hold semaphore to serialize pll init and fwtrc.
1841 	 */
1842 	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1843 		bfa_trc(ioc, 0);
1844 		return BFA_STATUS_FAILED;
1845 	}
1846 
1847 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1848 
1849 	len = sz/sizeof(u32);
1850 	bfa_trc(ioc, len);
1851 	for (i = 0; i < len; i++) {
1852 		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
1853 		buf[i] = be32_to_cpu(r32);
1854 		loff += sizeof(u32);
1855 
1856 		/*
1857 		 * handle page offset wrap around
1858 		 */
1859 		loff = PSS_SMEM_PGOFF(loff);
1860 		if (loff == 0) {
1861 			pgnum++;
1862 			writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1863 		}
1864 	}
1865 	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1866 			ioc->ioc_regs.host_page_num_fn);
1867 	/*
1868 	 *  release semaphore.
1869 	 */
1870 	readl(ioc->ioc_regs.ioc_init_sem_reg);
1871 	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1872 
1873 	bfa_trc(ioc, pgnum);
1874 	return BFA_STATUS_OK;
1875 }
1876 
1877 /*
1878  * Clear SMEM data from host through PCI memmap
1879  *
1880  * @param[in]	ioc	memory for IOC
1881  * @param[in]	soff	smem offset
1882  * @param[in]	sz	size of smem in bytes
1883  */
1884 static bfa_status_t
1885 bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
1886 {
1887 	int i, len;
1888 	u32 pgnum, loff;
1889 
1890 	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1891 	loff = PSS_SMEM_PGOFF(soff);
1892 	bfa_trc(ioc, pgnum);
1893 	bfa_trc(ioc, loff);
1894 	bfa_trc(ioc, sz);
1895 
1896 	/*
1897 	 *  Hold semaphore to serialize pll init and fwtrc.
1898 	 */
1899 	if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1900 		bfa_trc(ioc, 0);
1901 		return BFA_STATUS_FAILED;
1902 	}
1903 
1904 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1905 
1906 	len = sz/sizeof(u32); /* len in words */
1907 	bfa_trc(ioc, len);
1908 	for (i = 0; i < len; i++) {
1909 		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
1910 		loff += sizeof(u32);
1911 
1912 		/*
1913 		 * handle page offset wrap around
1914 		 */
1915 		loff = PSS_SMEM_PGOFF(loff);
1916 		if (loff == 0) {
1917 			pgnum++;
1918 			writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1919 		}
1920 	}
1921 	writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1922 			ioc->ioc_regs.host_page_num_fn);
1923 
1924 	/*
1925 	 *  release semaphore.
1926 	 */
1927 	readl(ioc->ioc_regs.ioc_init_sem_reg);
1928 	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1929 	bfa_trc(ioc, pgnum);
1930 	return BFA_STATUS_OK;
1931 }
1932 
1933 static void
1934 bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
1935 {
1936 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
1937 
1938 	/*
1939 	 * Notify driver and common modules registered for notification.
1940 	 */
1941 	ioc->cbfn->hbfail_cbfn(ioc->bfa);
1942 	bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
1943 
1944 	bfa_ioc_debug_save_ftrc(ioc);
1945 
1946 	BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
1947 		"Heart Beat of IOC has failed\n");
1948 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
1949 
1950 }
1951 
1952 static void
1953 bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
1954 {
1955 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
1956 	/*
1957 	 * Provide enable completion callback.
1958 	 */
1959 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
1960 	BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
1961 		"Running firmware version is incompatible "
1962 		"with the driver version\n");
1963 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
1964 }
1965 
1966 bfa_status_t
1967 bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1968 {
1969 
1970 	/*
1971 	 *  Hold semaphore so that nobody can access the chip during init.
1972 	 */
1973 	bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1974 
1975 	bfa_ioc_pll_init_asic(ioc);
1976 
1977 	ioc->pllinit = BFA_TRUE;
1978 
1979 	/*
1980 	 * Initialize LMEM
1981 	 */
1982 	bfa_ioc_lmem_init(ioc);
1983 
1984 	/*
1985 	 *  release semaphore.
1986 	 */
1987 	readl(ioc->ioc_regs.ioc_init_sem_reg);
1988 	writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1989 
1990 	return BFA_STATUS_OK;
1991 }
1992 
1993 /*
1994  * Interface used by diag module to do firmware boot with memory test
1995  * as the entry vector.
1996  */
1997 void
1998 bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
1999 {
2000 	bfa_ioc_stats(ioc, ioc_boots);
2001 
2002 	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
2003 		return;
2004 
2005 	/*
2006 	 * Initialize IOC state of all functions on a chip reset.
2007 	 */
2008 	if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
2009 		writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
2010 		writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
2011 	} else {
2012 		writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
2013 		writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
2014 	}
2015 
2016 	bfa_ioc_msgflush(ioc);
2017 	bfa_ioc_download_fw(ioc, boot_type, boot_env);
2018 	bfa_ioc_lpu_start(ioc);
2019 }
2020 
2021 /*
2022  * Enable/disable IOC failure auto recovery.
2023  */
2024 void
2025 bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
2026 {
2027 	bfa_auto_recover = auto_recover;
2028 }
2029 
2030 
2031 
2032 bfa_boolean_t
2033 bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
2034 {
2035 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
2036 }
2037 
2038 bfa_boolean_t
2039 bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
2040 {
2041 	u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
2042 
2043 	return ((r32 != BFI_IOC_UNINIT) &&
2044 		(r32 != BFI_IOC_INITING) &&
2045 		(r32 != BFI_IOC_MEMTEST));
2046 }
2047 
2048 bfa_boolean_t
2049 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
2050 {
2051 	__be32	*msgp = mbmsg;
2052 	u32	r32;
2053 	int		i;
2054 
2055 	r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
2056 	if ((r32 & 1) == 0)
2057 		return BFA_FALSE;
2058 
2059 	/*
2060 	 * read the MBOX msg
2061 	 */
2062 	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
2063 	     i++) {
2064 		r32 = readl(ioc->ioc_regs.lpu_mbox +
2065 				   i * sizeof(u32));
2066 		msgp[i] = cpu_to_be32(r32);
2067 	}
2068 
2069 	/*
2070 	 * turn off mailbox interrupt by clearing mailbox status
2071 	 */
2072 	writel(1, ioc->ioc_regs.lpu_mbox_cmd);
2073 	readl(ioc->ioc_regs.lpu_mbox_cmd);
2074 
2075 	return BFA_TRUE;
2076 }
2077 
2078 void
2079 bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
2080 {
2081 	union bfi_ioc_i2h_msg_u	*msg;
2082 	struct bfa_iocpf_s *iocpf = &ioc->iocpf;
2083 
2084 	msg = (union bfi_ioc_i2h_msg_u *) m;
2085 
2086 	bfa_ioc_stats(ioc, ioc_isrs);
2087 
2088 	switch (msg->mh.msg_id) {
2089 	case BFI_IOC_I2H_HBEAT:
2090 		break;
2091 
2092 	case BFI_IOC_I2H_ENABLE_REPLY:
2093 		ioc->port_mode = ioc->port_mode_cfg =
2094 				(enum bfa_mode_s)msg->fw_event.port_mode;
2095 		ioc->ad_cap_bm = msg->fw_event.cap_bm;
2096 		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
2097 		break;
2098 
2099 	case BFI_IOC_I2H_DISABLE_REPLY:
2100 		bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
2101 		break;
2102 
2103 	case BFI_IOC_I2H_GETATTR_REPLY:
2104 		bfa_ioc_getattr_reply(ioc);
2105 		break;
2106 
2107 	default:
2108 		bfa_trc(ioc, msg->mh.msg_id);
2109 		WARN_ON(1);
2110 	}
2111 }
2112 
2113 /*
2114  * IOC attach time initialization and setup.
2115  *
2116  * @param[in]	ioc	memory for IOC
2117  * @param[in]	bfa	driver instance structure
2118  */
2119 void
2120 bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
2121 	       struct bfa_timer_mod_s *timer_mod)
2122 {
2123 	ioc->bfa	= bfa;
2124 	ioc->cbfn	= cbfn;
2125 	ioc->timer_mod	= timer_mod;
2126 	ioc->fcmode	= BFA_FALSE;
2127 	ioc->pllinit	= BFA_FALSE;
2128 	ioc->dbg_fwsave_once = BFA_TRUE;
2129 	ioc->iocpf.ioc	= ioc;
2130 
2131 	bfa_ioc_mbox_attach(ioc);
2132 	INIT_LIST_HEAD(&ioc->notify_q);
2133 
2134 	bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
2135 	bfa_fsm_send_event(ioc, IOC_E_RESET);
2136 }
2137 
2138 /*
2139  * Driver detach time IOC cleanup.
2140  */
2141 void
2142 bfa_ioc_detach(struct bfa_ioc_s *ioc)
2143 {
2144 	bfa_fsm_send_event(ioc, IOC_E_DETACH);
2145 	INIT_LIST_HEAD(&ioc->notify_q);
2146 }
2147 
2148 /*
2149  * Setup IOC PCI properties.
2150  *
2151  * @param[in]	pcidev	PCI device information for this IOC
2152  */
2153 void
2154 bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
2155 		enum bfi_pcifn_class clscode)
2156 {
2157 	ioc->clscode	= clscode;
2158 	ioc->pcidev	= *pcidev;
2159 
2160 	/*
2161 	 * Initialize IOC and device personality
2162 	 */
2163 	ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
2164 	ioc->asic_mode  = BFI_ASIC_MODE_FC;
2165 
2166 	switch (pcidev->device_id) {
2167 	case BFA_PCI_DEVICE_ID_FC_8G1P:
2168 	case BFA_PCI_DEVICE_ID_FC_8G2P:
2169 		ioc->asic_gen = BFI_ASIC_GEN_CB;
2170 		ioc->fcmode = BFA_TRUE;
2171 		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2172 		ioc->ad_cap_bm = BFA_CM_HBA;
2173 		break;
2174 
2175 	case BFA_PCI_DEVICE_ID_CT:
2176 		ioc->asic_gen = BFI_ASIC_GEN_CT;
2177 		ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2178 		ioc->asic_mode  = BFI_ASIC_MODE_ETH;
2179 		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
2180 		ioc->ad_cap_bm = BFA_CM_CNA;
2181 		break;
2182 
2183 	case BFA_PCI_DEVICE_ID_CT_FC:
2184 		ioc->asic_gen = BFI_ASIC_GEN_CT;
2185 		ioc->fcmode = BFA_TRUE;
2186 		ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2187 		ioc->ad_cap_bm = BFA_CM_HBA;
2188 		break;
2189 
2190 	case BFA_PCI_DEVICE_ID_CT2:
2191 		ioc->asic_gen = BFI_ASIC_GEN_CT2;
2192 		if (clscode == BFI_PCIFN_CLASS_FC &&
2193 		    pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
2194 			ioc->asic_mode  = BFI_ASIC_MODE_FC16;
2195 			ioc->fcmode = BFA_TRUE;
2196 			ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2197 			ioc->ad_cap_bm = BFA_CM_HBA;
2198 		} else {
2199 			ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2200 			ioc->asic_mode  = BFI_ASIC_MODE_ETH;
2201 			if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {
2202 				ioc->port_mode =
2203 				ioc->port_mode_cfg = BFA_MODE_CNA;
2204 				ioc->ad_cap_bm = BFA_CM_CNA;
2205 			} else {
2206 				ioc->port_mode =
2207 				ioc->port_mode_cfg = BFA_MODE_NIC;
2208 				ioc->ad_cap_bm = BFA_CM_NIC;
2209 			}
2210 		}
2211 		break;
2212 
2213 	default:
2214 		WARN_ON(1);
2215 	}
2216 
2217 	/*
2218 	 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
2219 	 */
2220 	if (ioc->asic_gen == BFI_ASIC_GEN_CB)
2221 		bfa_ioc_set_cb_hwif(ioc);
2222 	else if (ioc->asic_gen == BFI_ASIC_GEN_CT)
2223 		bfa_ioc_set_ct_hwif(ioc);
2224 	else {
2225 		WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
2226 		bfa_ioc_set_ct2_hwif(ioc);
2227 		bfa_ioc_ct2_poweron(ioc);
2228 	}
2229 
2230 	bfa_ioc_map_port(ioc);
2231 	bfa_ioc_reg_init(ioc);
2232 }
2233 
2234 /*
2235  * Initialize IOC dma memory
2236  *
2237  * @param[in]	dm_kva	kernel virtual address of IOC dma memory
2238  * @param[in]	dm_pa	physical address of IOC dma memory
2239  */
2240 void
2241 bfa_ioc_mem_claim(struct bfa_ioc_s *ioc,  u8 *dm_kva, u64 dm_pa)
2242 {
2243 	/*
2244 	 * dma memory for firmware attribute
2245 	 */
2246 	ioc->attr_dma.kva = dm_kva;
2247 	ioc->attr_dma.pa = dm_pa;
2248 	ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
2249 }
2250 
2251 void
2252 bfa_ioc_enable(struct bfa_ioc_s *ioc)
2253 {
2254 	bfa_ioc_stats(ioc, ioc_enables);
2255 	ioc->dbg_fwsave_once = BFA_TRUE;
2256 
2257 	bfa_fsm_send_event(ioc, IOC_E_ENABLE);
2258 }
2259 
2260 void
2261 bfa_ioc_disable(struct bfa_ioc_s *ioc)
2262 {
2263 	bfa_ioc_stats(ioc, ioc_disables);
2264 	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
2265 }
2266 
2267 void
2268 bfa_ioc_suspend(struct bfa_ioc_s *ioc)
2269 {
2270 	ioc->dbg_fwsave_once = BFA_TRUE;
2271 	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2272 }
2273 
2274 /*
2275  * Initialize memory for saving firmware trace. Driver must initialize
2276  * trace memory before call bfa_ioc_enable().
2277  */
2278 void
2279 bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
2280 {
2281 	ioc->dbg_fwsave	    = dbg_fwsave;
2282 	ioc->dbg_fwsave_len = BFA_DBG_FWTRC_LEN;
2283 }
2284 
2285 /*
2286  * Register mailbox message handler functions
2287  *
2288  * @param[in]	ioc		IOC instance
2289  * @param[in]	mcfuncs		message class handler functions
2290  */
2291 void
2292 bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
2293 {
2294 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
2295 	int				mc;
2296 
2297 	for (mc = 0; mc < BFI_MC_MAX; mc++)
2298 		mod->mbhdlr[mc].cbfn = mcfuncs[mc];
2299 }
2300 
2301 /*
2302  * Register mailbox message handler function, to be called by common modules
2303  */
2304 void
2305 bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
2306 		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2307 {
2308 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
2309 
2310 	mod->mbhdlr[mc].cbfn	= cbfn;
2311 	mod->mbhdlr[mc].cbarg	= cbarg;
2312 }
2313 
2314 /*
2315  * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2316  * Responsibility of caller to serialize
2317  *
2318  * @param[in]	ioc	IOC instance
2319  * @param[i]	cmd	Mailbox command
2320  */
2321 void
2322 bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
2323 {
2324 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
2325 	u32			stat;
2326 
2327 	/*
2328 	 * If a previous command is pending, queue new command
2329 	 */
2330 	if (!list_empty(&mod->cmd_q)) {
2331 		list_add_tail(&cmd->qe, &mod->cmd_q);
2332 		return;
2333 	}
2334 
2335 	/*
2336 	 * If mailbox is busy, queue command for poll timer
2337 	 */
2338 	stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
2339 	if (stat) {
2340 		list_add_tail(&cmd->qe, &mod->cmd_q);
2341 		return;
2342 	}
2343 
2344 	/*
2345 	 * mailbox is free -- queue command to firmware
2346 	 */
2347 	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
2348 }
2349 
2350 /*
2351  * Handle mailbox interrupts
2352  */
2353 void
2354 bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
2355 {
2356 	struct bfa_ioc_mbox_mod_s	*mod = &ioc->mbox_mod;
2357 	struct bfi_mbmsg_s		m;
2358 	int				mc;
2359 
2360 	if (bfa_ioc_msgget(ioc, &m)) {
2361 		/*
2362 		 * Treat IOC message class as special.
2363 		 */
2364 		mc = m.mh.msg_class;
2365 		if (mc == BFI_MC_IOC) {
2366 			bfa_ioc_isr(ioc, &m);
2367 			return;
2368 		}
2369 
2370 		if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2371 			return;
2372 
2373 		mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
2374 	}
2375 
2376 	bfa_ioc_lpu_read_stat(ioc);
2377 
2378 	/*
2379 	 * Try to send pending mailbox commands
2380 	 */
2381 	bfa_ioc_mbox_poll(ioc);
2382 }
2383 
2384 void
2385 bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
2386 {
2387 	bfa_ioc_stats(ioc, ioc_hbfails);
2388 	ioc->stats.hb_count = ioc->hb_count;
2389 	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2390 }
2391 
2392 /*
2393  * return true if IOC is disabled
2394  */
2395 bfa_boolean_t
2396 bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
2397 {
2398 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2399 		bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
2400 }
2401 
2402 /*
2403  * return true if IOC firmware is different.
2404  */
2405 bfa_boolean_t
2406 bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2407 {
2408 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
2409 		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
2410 		bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
2411 }
2412 
2413 #define bfa_ioc_state_disabled(__sm)		\
2414 	(((__sm) == BFI_IOC_UNINIT) ||		\
2415 	 ((__sm) == BFI_IOC_INITING) ||		\
2416 	 ((__sm) == BFI_IOC_HWINIT) ||		\
2417 	 ((__sm) == BFI_IOC_DISABLED) ||	\
2418 	 ((__sm) == BFI_IOC_FAIL) ||		\
2419 	 ((__sm) == BFI_IOC_CFG_DISABLED))
2420 
2421 /*
2422  * Check if adapter is disabled -- both IOCs should be in a disabled
2423  * state.
2424  */
2425 bfa_boolean_t
2426 bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
2427 {
2428 	u32	ioc_state;
2429 
2430 	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
2431 		return BFA_FALSE;
2432 
2433 	ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
2434 	if (!bfa_ioc_state_disabled(ioc_state))
2435 		return BFA_FALSE;
2436 
2437 	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
2438 		ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
2439 		if (!bfa_ioc_state_disabled(ioc_state))
2440 			return BFA_FALSE;
2441 	}
2442 
2443 	return BFA_TRUE;
2444 }
2445 
2446 /*
2447  * Reset IOC fwstate registers.
2448  */
2449 void
2450 bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
2451 {
2452 	writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
2453 	writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
2454 }
2455 
2456 #define BFA_MFG_NAME "Brocade"
2457 void
2458 bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2459 			 struct bfa_adapter_attr_s *ad_attr)
2460 {
2461 	struct bfi_ioc_attr_s	*ioc_attr;
2462 
2463 	ioc_attr = ioc->attr;
2464 
2465 	bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2466 	bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2467 	bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2468 	bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
2469 	memcpy(&ad_attr->vpd, &ioc_attr->vpd,
2470 		      sizeof(struct bfa_mfg_vpd_s));
2471 
2472 	ad_attr->nports = bfa_ioc_get_nports(ioc);
2473 	ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
2474 
2475 	bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2476 	/* For now, model descr uses same model string */
2477 	bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
2478 
2479 	ad_attr->card_type = ioc_attr->card_type;
2480 	ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2481 
2482 	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2483 		ad_attr->prototype = 1;
2484 	else
2485 		ad_attr->prototype = 0;
2486 
2487 	ad_attr->pwwn = ioc->attr->pwwn;
2488 	ad_attr->mac  = bfa_ioc_get_mac(ioc);
2489 
2490 	ad_attr->pcie_gen = ioc_attr->pcie_gen;
2491 	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2492 	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2493 	ad_attr->asic_rev = ioc_attr->asic_rev;
2494 
2495 	bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
2496 
2497 	ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
2498 	ad_attr->trunk_capable = (ad_attr->nports > 1) &&
2499 				  !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
2500 	ad_attr->mfg_day = ioc_attr->mfg_day;
2501 	ad_attr->mfg_month = ioc_attr->mfg_month;
2502 	ad_attr->mfg_year = ioc_attr->mfg_year;
2503 }
2504 
2505 enum bfa_ioc_type_e
2506 bfa_ioc_get_type(struct bfa_ioc_s *ioc)
2507 {
2508 	if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
2509 		return BFA_IOC_TYPE_LL;
2510 
2511 	WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC);
2512 
2513 	return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
2514 		? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
2515 }
2516 
2517 void
2518 bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)
2519 {
2520 	memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2521 	memcpy((void *)serial_num,
2522 			(void *)ioc->attr->brcd_serialnum,
2523 			BFA_ADAPTER_SERIAL_NUM_LEN);
2524 }
2525 
2526 void
2527 bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
2528 {
2529 	memset((void *)fw_ver, 0, BFA_VERSION_LEN);
2530 	memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
2531 }
2532 
2533 void
2534 bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
2535 {
2536 	WARN_ON(!chip_rev);
2537 
2538 	memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
2539 
2540 	chip_rev[0] = 'R';
2541 	chip_rev[1] = 'e';
2542 	chip_rev[2] = 'v';
2543 	chip_rev[3] = '-';
2544 	chip_rev[4] = ioc->attr->asic_rev;
2545 	chip_rev[5] = '\0';
2546 }
2547 
2548 void
2549 bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
2550 {
2551 	memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
2552 	memcpy(optrom_ver, ioc->attr->optrom_version,
2553 		      BFA_VERSION_LEN);
2554 }
2555 
2556 void
2557 bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
2558 {
2559 	memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2560 	memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
2561 }
2562 
2563 void
2564 bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
2565 {
2566 	struct bfi_ioc_attr_s	*ioc_attr;
2567 
2568 	WARN_ON(!model);
2569 	memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
2570 
2571 	ioc_attr = ioc->attr;
2572 
2573 	snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
2574 			BFA_MFG_NAME, ioc_attr->card_type);
2575 }
2576 
2577 enum bfa_ioc_state
2578 bfa_ioc_get_state(struct bfa_ioc_s *ioc)
2579 {
2580 	enum bfa_iocpf_state iocpf_st;
2581 	enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2582 
2583 	if (ioc_st == BFA_IOC_ENABLING ||
2584 		ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2585 
2586 		iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2587 
2588 		switch (iocpf_st) {
2589 		case BFA_IOCPF_SEMWAIT:
2590 			ioc_st = BFA_IOC_SEMWAIT;
2591 			break;
2592 
2593 		case BFA_IOCPF_HWINIT:
2594 			ioc_st = BFA_IOC_HWINIT;
2595 			break;
2596 
2597 		case BFA_IOCPF_FWMISMATCH:
2598 			ioc_st = BFA_IOC_FWMISMATCH;
2599 			break;
2600 
2601 		case BFA_IOCPF_FAIL:
2602 			ioc_st = BFA_IOC_FAIL;
2603 			break;
2604 
2605 		case BFA_IOCPF_INITFAIL:
2606 			ioc_st = BFA_IOC_INITFAIL;
2607 			break;
2608 
2609 		default:
2610 			break;
2611 		}
2612 	}
2613 
2614 	return ioc_st;
2615 }
2616 
2617 void
2618 bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2619 {
2620 	memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
2621 
2622 	ioc_attr->state = bfa_ioc_get_state(ioc);
2623 	ioc_attr->port_id = ioc->port_id;
2624 	ioc_attr->port_mode = ioc->port_mode;
2625 	ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
2626 	ioc_attr->cap_bm = ioc->ad_cap_bm;
2627 
2628 	ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
2629 
2630 	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2631 
2632 	ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2633 	ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
2634 	bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
2635 }
2636 
2637 mac_t
2638 bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2639 {
2640 	/*
2641 	 * Check the IOC type and return the appropriate MAC
2642 	 */
2643 	if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
2644 		return ioc->attr->fcoe_mac;
2645 	else
2646 		return ioc->attr->mac;
2647 }
2648 
2649 mac_t
2650 bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
2651 {
2652 	mac_t	m;
2653 
2654 	m = ioc->attr->mfg_mac;
2655 	if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
2656 		m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2657 	else
2658 		bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
2659 			bfa_ioc_pcifn(ioc));
2660 
2661 	return m;
2662 }
2663 
2664 /*
2665  * Send AEN notification
2666  */
2667 void
2668 bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
2669 {
2670 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
2671 	struct bfa_aen_entry_s	*aen_entry;
2672 	enum bfa_ioc_type_e ioc_type;
2673 
2674 	bfad_get_aen_entry(bfad, aen_entry);
2675 	if (!aen_entry)
2676 		return;
2677 
2678 	ioc_type = bfa_ioc_get_type(ioc);
2679 	switch (ioc_type) {
2680 	case BFA_IOC_TYPE_FC:
2681 		aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;
2682 		break;
2683 	case BFA_IOC_TYPE_FCoE:
2684 		aen_entry->aen_data.ioc.pwwn = ioc->attr->pwwn;
2685 		aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
2686 		break;
2687 	case BFA_IOC_TYPE_LL:
2688 		aen_entry->aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
2689 		break;
2690 	default:
2691 		WARN_ON(ioc_type != BFA_IOC_TYPE_FC);
2692 		break;
2693 	}
2694 
2695 	/* Send the AEN notification */
2696 	aen_entry->aen_data.ioc.ioc_type = ioc_type;
2697 	bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,
2698 				  BFA_AEN_CAT_IOC, event);
2699 }
2700 
2701 /*
2702  * Retrieve saved firmware trace from a prior IOC failure.
2703  */
2704 bfa_status_t
2705 bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2706 {
2707 	int	tlen;
2708 
2709 	if (ioc->dbg_fwsave_len == 0)
2710 		return BFA_STATUS_ENOFSAVE;
2711 
2712 	tlen = *trclen;
2713 	if (tlen > ioc->dbg_fwsave_len)
2714 		tlen = ioc->dbg_fwsave_len;
2715 
2716 	memcpy(trcdata, ioc->dbg_fwsave, tlen);
2717 	*trclen = tlen;
2718 	return BFA_STATUS_OK;
2719 }
2720 
2721 
2722 /*
2723  * Retrieve saved firmware trace from a prior IOC failure.
2724  */
2725 bfa_status_t
2726 bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2727 {
2728 	u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2729 	int tlen;
2730 	bfa_status_t status;
2731 
2732 	bfa_trc(ioc, *trclen);
2733 
2734 	tlen = *trclen;
2735 	if (tlen > BFA_DBG_FWTRC_LEN)
2736 		tlen = BFA_DBG_FWTRC_LEN;
2737 
2738 	status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
2739 	*trclen = tlen;
2740 	return status;
2741 }
2742 
2743 static void
2744 bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
2745 {
2746 	struct bfa_mbox_cmd_s cmd;
2747 	struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
2748 
2749 	bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
2750 		    bfa_ioc_portid(ioc));
2751 	req->clscode = cpu_to_be16(ioc->clscode);
2752 	bfa_ioc_mbox_queue(ioc, &cmd);
2753 }
2754 
2755 static void
2756 bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
2757 {
2758 	u32 fwsync_iter = 1000;
2759 
2760 	bfa_ioc_send_fwsync(ioc);
2761 
2762 	/*
2763 	 * After sending a fw sync mbox command wait for it to
2764 	 * take effect.  We will not wait for a response because
2765 	 *    1. fw_sync mbox cmd doesn't have a response.
2766 	 *    2. Even if we implement that,  interrupts might not
2767 	 *	 be enabled when we call this function.
2768 	 * So, just keep checking if any mbox cmd is pending, and
2769 	 * after waiting for a reasonable amount of time, go ahead.
2770 	 * It is possible that fw has crashed and the mbox command
2771 	 * is never acknowledged.
2772 	 */
2773 	while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
2774 		fwsync_iter--;
2775 }
2776 
2777 /*
2778  * Dump firmware smem
2779  */
2780 bfa_status_t
2781 bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
2782 				u32 *offset, int *buflen)
2783 {
2784 	u32 loff;
2785 	int dlen;
2786 	bfa_status_t status;
2787 	u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
2788 
2789 	if (*offset >= smem_len) {
2790 		*offset = *buflen = 0;
2791 		return BFA_STATUS_EINVAL;
2792 	}
2793 
2794 	loff = *offset;
2795 	dlen = *buflen;
2796 
2797 	/*
2798 	 * First smem read, sync smem before proceeding
2799 	 * No need to sync before reading every chunk.
2800 	 */
2801 	if (loff == 0)
2802 		bfa_ioc_fwsync(ioc);
2803 
2804 	if ((loff + dlen) >= smem_len)
2805 		dlen = smem_len - loff;
2806 
2807 	status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
2808 
2809 	if (status != BFA_STATUS_OK) {
2810 		*offset = *buflen = 0;
2811 		return status;
2812 	}
2813 
2814 	*offset += dlen;
2815 
2816 	if (*offset >= smem_len)
2817 		*offset = 0;
2818 
2819 	*buflen = dlen;
2820 
2821 	return status;
2822 }
2823 
2824 /*
2825  * Firmware statistics
2826  */
2827 bfa_status_t
2828 bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
2829 {
2830 	u32 loff = BFI_IOC_FWSTATS_OFF + \
2831 		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2832 	int tlen;
2833 	bfa_status_t status;
2834 
2835 	if (ioc->stats_busy) {
2836 		bfa_trc(ioc, ioc->stats_busy);
2837 		return BFA_STATUS_DEVBUSY;
2838 	}
2839 	ioc->stats_busy = BFA_TRUE;
2840 
2841 	tlen = sizeof(struct bfa_fw_stats_s);
2842 	status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
2843 
2844 	ioc->stats_busy = BFA_FALSE;
2845 	return status;
2846 }
2847 
2848 bfa_status_t
2849 bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2850 {
2851 	u32 loff = BFI_IOC_FWSTATS_OFF + \
2852 		BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2853 	int tlen;
2854 	bfa_status_t status;
2855 
2856 	if (ioc->stats_busy) {
2857 		bfa_trc(ioc, ioc->stats_busy);
2858 		return BFA_STATUS_DEVBUSY;
2859 	}
2860 	ioc->stats_busy = BFA_TRUE;
2861 
2862 	tlen = sizeof(struct bfa_fw_stats_s);
2863 	status = bfa_ioc_smem_clr(ioc, loff, tlen);
2864 
2865 	ioc->stats_busy = BFA_FALSE;
2866 	return status;
2867 }
2868 
2869 /*
2870  * Save firmware trace if configured.
2871  */
2872 void
2873 bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
2874 {
2875 	int		tlen;
2876 
2877 	if (ioc->dbg_fwsave_once) {
2878 		ioc->dbg_fwsave_once = BFA_FALSE;
2879 		if (ioc->dbg_fwsave_len) {
2880 			tlen = ioc->dbg_fwsave_len;
2881 			bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2882 		}
2883 	}
2884 }
2885 
2886 /*
2887  * Firmware failure detected. Start recovery actions.
2888  */
2889 static void
2890 bfa_ioc_recover(struct bfa_ioc_s *ioc)
2891 {
2892 	bfa_ioc_stats(ioc, ioc_hbfails);
2893 	ioc->stats.hb_count = ioc->hb_count;
2894 	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2895 }
2896 
2897 /*
2898  *  BFA IOC PF private functions
2899  */
2900 static void
2901 bfa_iocpf_timeout(void *ioc_arg)
2902 {
2903 	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
2904 
2905 	bfa_trc(ioc, 0);
2906 	bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
2907 }
2908 
2909 static void
2910 bfa_iocpf_sem_timeout(void *ioc_arg)
2911 {
2912 	struct bfa_ioc_s  *ioc = (struct bfa_ioc_s *) ioc_arg;
2913 
2914 	bfa_ioc_hw_sem_get(ioc);
2915 }
2916 
2917 static void
2918 bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
2919 {
2920 	u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
2921 
2922 	bfa_trc(ioc, fwstate);
2923 
2924 	if (fwstate == BFI_IOC_DISABLED) {
2925 		bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
2926 		return;
2927 	}
2928 
2929 	if (ioc->iocpf.poll_time >= (3 * BFA_IOC_TOV))
2930 		bfa_iocpf_timeout(ioc);
2931 	else {
2932 		ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
2933 		bfa_iocpf_poll_timer_start(ioc);
2934 	}
2935 }
2936 
2937 static void
2938 bfa_iocpf_poll_timeout(void *ioc_arg)
2939 {
2940 	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2941 
2942 	bfa_ioc_poll_fwinit(ioc);
2943 }
2944 
2945 /*
2946  *  bfa timer function
2947  */
2948 void
2949 bfa_timer_beat(struct bfa_timer_mod_s *mod)
2950 {
2951 	struct list_head *qh = &mod->timer_q;
2952 	struct list_head *qe, *qe_next;
2953 	struct bfa_timer_s *elem;
2954 	struct list_head timedout_q;
2955 
2956 	INIT_LIST_HEAD(&timedout_q);
2957 
2958 	qe = bfa_q_next(qh);
2959 
2960 	while (qe != qh) {
2961 		qe_next = bfa_q_next(qe);
2962 
2963 		elem = (struct bfa_timer_s *) qe;
2964 		if (elem->timeout <= BFA_TIMER_FREQ) {
2965 			elem->timeout = 0;
2966 			list_del(&elem->qe);
2967 			list_add_tail(&elem->qe, &timedout_q);
2968 		} else {
2969 			elem->timeout -= BFA_TIMER_FREQ;
2970 		}
2971 
2972 		qe = qe_next;	/* go to next elem */
2973 	}
2974 
2975 	/*
2976 	 * Pop all the timeout entries
2977 	 */
2978 	while (!list_empty(&timedout_q)) {
2979 		bfa_q_deq(&timedout_q, &elem);
2980 		elem->timercb(elem->arg);
2981 	}
2982 }
2983 
2984 /*
2985  * Should be called with lock protection
2986  */
2987 void
2988 bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
2989 		    void (*timercb) (void *), void *arg, unsigned int timeout)
2990 {
2991 
2992 	WARN_ON(timercb == NULL);
2993 	WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));
2994 
2995 	timer->timeout = timeout;
2996 	timer->timercb = timercb;
2997 	timer->arg = arg;
2998 
2999 	list_add_tail(&timer->qe, &mod->timer_q);
3000 }
3001 
3002 /*
3003  * Should be called with lock protection
3004  */
3005 void
3006 bfa_timer_stop(struct bfa_timer_s *timer)
3007 {
3008 	WARN_ON(list_empty(&timer->qe));
3009 
3010 	list_del(&timer->qe);
3011 }
3012 
3013 /*
3014  *	ASIC block related
3015  */
3016 static void
3017 bfa_ablk_config_swap(struct bfa_ablk_cfg_s *cfg)
3018 {
3019 	struct bfa_ablk_cfg_inst_s *cfg_inst;
3020 	int i, j;
3021 	u16	be16;
3022 
3023 	for (i = 0; i < BFA_ABLK_MAX; i++) {
3024 		cfg_inst = &cfg->inst[i];
3025 		for (j = 0; j < BFA_ABLK_MAX_PFS; j++) {
3026 			be16 = cfg_inst->pf_cfg[j].pers;
3027 			cfg_inst->pf_cfg[j].pers = be16_to_cpu(be16);
3028 			be16 = cfg_inst->pf_cfg[j].num_qpairs;
3029 			cfg_inst->pf_cfg[j].num_qpairs = be16_to_cpu(be16);
3030 			be16 = cfg_inst->pf_cfg[j].num_vectors;
3031 			cfg_inst->pf_cfg[j].num_vectors = be16_to_cpu(be16);
3032 			be16 = cfg_inst->pf_cfg[j].bw_min;
3033 			cfg_inst->pf_cfg[j].bw_min = be16_to_cpu(be16);
3034 			be16 = cfg_inst->pf_cfg[j].bw_max;
3035 			cfg_inst->pf_cfg[j].bw_max = be16_to_cpu(be16);
3036 		}
3037 	}
3038 }
3039 
3040 static void
3041 bfa_ablk_isr(void *cbarg, struct bfi_mbmsg_s *msg)
3042 {
3043 	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
3044 	struct bfi_ablk_i2h_rsp_s *rsp = (struct bfi_ablk_i2h_rsp_s *)msg;
3045 	bfa_ablk_cbfn_t cbfn;
3046 
3047 	WARN_ON(msg->mh.msg_class != BFI_MC_ABLK);
3048 	bfa_trc(ablk->ioc, msg->mh.msg_id);
3049 
3050 	switch (msg->mh.msg_id) {
3051 	case BFI_ABLK_I2H_QUERY:
3052 		if (rsp->status == BFA_STATUS_OK) {
3053 			memcpy(ablk->cfg, ablk->dma_addr.kva,
3054 				sizeof(struct bfa_ablk_cfg_s));
3055 			bfa_ablk_config_swap(ablk->cfg);
3056 			ablk->cfg = NULL;
3057 		}
3058 		break;
3059 
3060 	case BFI_ABLK_I2H_ADPT_CONFIG:
3061 	case BFI_ABLK_I2H_PORT_CONFIG:
3062 		/* update config port mode */
3063 		ablk->ioc->port_mode_cfg = rsp->port_mode;
3064 
3065 	case BFI_ABLK_I2H_PF_DELETE:
3066 	case BFI_ABLK_I2H_PF_UPDATE:
3067 	case BFI_ABLK_I2H_OPTROM_ENABLE:
3068 	case BFI_ABLK_I2H_OPTROM_DISABLE:
3069 		/* No-op */
3070 		break;
3071 
3072 	case BFI_ABLK_I2H_PF_CREATE:
3073 		*(ablk->pcifn) = rsp->pcifn;
3074 		ablk->pcifn = NULL;
3075 		break;
3076 
3077 	default:
3078 		WARN_ON(1);
3079 	}
3080 
3081 	ablk->busy = BFA_FALSE;
3082 	if (ablk->cbfn) {
3083 		cbfn = ablk->cbfn;
3084 		ablk->cbfn = NULL;
3085 		cbfn(ablk->cbarg, rsp->status);
3086 	}
3087 }
3088 
3089 static void
3090 bfa_ablk_notify(void *cbarg, enum bfa_ioc_event_e event)
3091 {
3092 	struct bfa_ablk_s *ablk = (struct bfa_ablk_s *)cbarg;
3093 
3094 	bfa_trc(ablk->ioc, event);
3095 
3096 	switch (event) {
3097 	case BFA_IOC_E_ENABLED:
3098 		WARN_ON(ablk->busy != BFA_FALSE);
3099 		break;
3100 
3101 	case BFA_IOC_E_DISABLED:
3102 	case BFA_IOC_E_FAILED:
3103 		/* Fail any pending requests */
3104 		ablk->pcifn = NULL;
3105 		if (ablk->busy) {
3106 			if (ablk->cbfn)
3107 				ablk->cbfn(ablk->cbarg, BFA_STATUS_FAILED);
3108 			ablk->cbfn = NULL;
3109 			ablk->busy = BFA_FALSE;
3110 		}
3111 		break;
3112 
3113 	default:
3114 		WARN_ON(1);
3115 		break;
3116 	}
3117 }
3118 
3119 u32
3120 bfa_ablk_meminfo(void)
3121 {
3122 	return BFA_ROUNDUP(sizeof(struct bfa_ablk_cfg_s), BFA_DMA_ALIGN_SZ);
3123 }
3124 
3125 void
3126 bfa_ablk_memclaim(struct bfa_ablk_s *ablk, u8 *dma_kva, u64 dma_pa)
3127 {
3128 	ablk->dma_addr.kva = dma_kva;
3129 	ablk->dma_addr.pa  = dma_pa;
3130 }
3131 
3132 void
3133 bfa_ablk_attach(struct bfa_ablk_s *ablk, struct bfa_ioc_s *ioc)
3134 {
3135 	ablk->ioc = ioc;
3136 
3137 	bfa_ioc_mbox_regisr(ablk->ioc, BFI_MC_ABLK, bfa_ablk_isr, ablk);
3138 	bfa_q_qe_init(&ablk->ioc_notify);
3139 	bfa_ioc_notify_init(&ablk->ioc_notify, bfa_ablk_notify, ablk);
3140 	list_add_tail(&ablk->ioc_notify.qe, &ablk->ioc->notify_q);
3141 }
3142 
3143 bfa_status_t
3144 bfa_ablk_query(struct bfa_ablk_s *ablk, struct bfa_ablk_cfg_s *ablk_cfg,
3145 		bfa_ablk_cbfn_t cbfn, void *cbarg)
3146 {
3147 	struct bfi_ablk_h2i_query_s *m;
3148 
3149 	WARN_ON(!ablk_cfg);
3150 
3151 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3152 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3153 		return BFA_STATUS_IOC_FAILURE;
3154 	}
3155 
3156 	if (ablk->busy) {
3157 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3158 		return  BFA_STATUS_DEVBUSY;
3159 	}
3160 
3161 	ablk->cfg = ablk_cfg;
3162 	ablk->cbfn  = cbfn;
3163 	ablk->cbarg = cbarg;
3164 	ablk->busy  = BFA_TRUE;
3165 
3166 	m = (struct bfi_ablk_h2i_query_s *)ablk->mb.msg;
3167 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_QUERY,
3168 		    bfa_ioc_portid(ablk->ioc));
3169 	bfa_dma_be_addr_set(m->addr, ablk->dma_addr.pa);
3170 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3171 
3172 	return BFA_STATUS_OK;
3173 }
3174 
3175 bfa_status_t
3176 bfa_ablk_pf_create(struct bfa_ablk_s *ablk, u16 *pcifn,
3177 		u8 port, enum bfi_pcifn_class personality,
3178 		u16 bw_min, u16 bw_max,
3179 		bfa_ablk_cbfn_t cbfn, void *cbarg)
3180 {
3181 	struct bfi_ablk_h2i_pf_req_s *m;
3182 
3183 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3184 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3185 		return BFA_STATUS_IOC_FAILURE;
3186 	}
3187 
3188 	if (ablk->busy) {
3189 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3190 		return  BFA_STATUS_DEVBUSY;
3191 	}
3192 
3193 	ablk->pcifn = pcifn;
3194 	ablk->cbfn = cbfn;
3195 	ablk->cbarg = cbarg;
3196 	ablk->busy  = BFA_TRUE;
3197 
3198 	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
3199 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_CREATE,
3200 		    bfa_ioc_portid(ablk->ioc));
3201 	m->pers = cpu_to_be16((u16)personality);
3202 	m->bw_min = cpu_to_be16(bw_min);
3203 	m->bw_max = cpu_to_be16(bw_max);
3204 	m->port = port;
3205 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3206 
3207 	return BFA_STATUS_OK;
3208 }
3209 
3210 bfa_status_t
3211 bfa_ablk_pf_delete(struct bfa_ablk_s *ablk, int pcifn,
3212 		bfa_ablk_cbfn_t cbfn, void *cbarg)
3213 {
3214 	struct bfi_ablk_h2i_pf_req_s *m;
3215 
3216 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3217 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3218 		return BFA_STATUS_IOC_FAILURE;
3219 	}
3220 
3221 	if (ablk->busy) {
3222 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3223 		return  BFA_STATUS_DEVBUSY;
3224 	}
3225 
3226 	ablk->cbfn  = cbfn;
3227 	ablk->cbarg = cbarg;
3228 	ablk->busy  = BFA_TRUE;
3229 
3230 	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
3231 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_DELETE,
3232 		    bfa_ioc_portid(ablk->ioc));
3233 	m->pcifn = (u8)pcifn;
3234 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3235 
3236 	return BFA_STATUS_OK;
3237 }
3238 
3239 bfa_status_t
3240 bfa_ablk_adapter_config(struct bfa_ablk_s *ablk, enum bfa_mode_s mode,
3241 		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
3242 {
3243 	struct bfi_ablk_h2i_cfg_req_s *m;
3244 
3245 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3246 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3247 		return BFA_STATUS_IOC_FAILURE;
3248 	}
3249 
3250 	if (ablk->busy) {
3251 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3252 		return  BFA_STATUS_DEVBUSY;
3253 	}
3254 
3255 	ablk->cbfn  = cbfn;
3256 	ablk->cbarg = cbarg;
3257 	ablk->busy  = BFA_TRUE;
3258 
3259 	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
3260 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_ADPT_CONFIG,
3261 		    bfa_ioc_portid(ablk->ioc));
3262 	m->mode = (u8)mode;
3263 	m->max_pf = (u8)max_pf;
3264 	m->max_vf = (u8)max_vf;
3265 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3266 
3267 	return BFA_STATUS_OK;
3268 }
3269 
3270 bfa_status_t
3271 bfa_ablk_port_config(struct bfa_ablk_s *ablk, int port, enum bfa_mode_s mode,
3272 		int max_pf, int max_vf, bfa_ablk_cbfn_t cbfn, void *cbarg)
3273 {
3274 	struct bfi_ablk_h2i_cfg_req_s *m;
3275 
3276 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3277 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3278 		return BFA_STATUS_IOC_FAILURE;
3279 	}
3280 
3281 	if (ablk->busy) {
3282 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3283 		return  BFA_STATUS_DEVBUSY;
3284 	}
3285 
3286 	ablk->cbfn  = cbfn;
3287 	ablk->cbarg = cbarg;
3288 	ablk->busy  = BFA_TRUE;
3289 
3290 	m = (struct bfi_ablk_h2i_cfg_req_s *)ablk->mb.msg;
3291 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PORT_CONFIG,
3292 		bfa_ioc_portid(ablk->ioc));
3293 	m->port = (u8)port;
3294 	m->mode = (u8)mode;
3295 	m->max_pf = (u8)max_pf;
3296 	m->max_vf = (u8)max_vf;
3297 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3298 
3299 	return BFA_STATUS_OK;
3300 }
3301 
3302 bfa_status_t
3303 bfa_ablk_pf_update(struct bfa_ablk_s *ablk, int pcifn, u16 bw_min,
3304 		   u16 bw_max, bfa_ablk_cbfn_t cbfn, void *cbarg)
3305 {
3306 	struct bfi_ablk_h2i_pf_req_s *m;
3307 
3308 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3309 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3310 		return BFA_STATUS_IOC_FAILURE;
3311 	}
3312 
3313 	if (ablk->busy) {
3314 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3315 		return  BFA_STATUS_DEVBUSY;
3316 	}
3317 
3318 	ablk->cbfn  = cbfn;
3319 	ablk->cbarg = cbarg;
3320 	ablk->busy  = BFA_TRUE;
3321 
3322 	m = (struct bfi_ablk_h2i_pf_req_s *)ablk->mb.msg;
3323 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_PF_UPDATE,
3324 		bfa_ioc_portid(ablk->ioc));
3325 	m->pcifn = (u8)pcifn;
3326 	m->bw_min = cpu_to_be16(bw_min);
3327 	m->bw_max = cpu_to_be16(bw_max);
3328 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3329 
3330 	return BFA_STATUS_OK;
3331 }
3332 
3333 bfa_status_t
3334 bfa_ablk_optrom_en(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
3335 {
3336 	struct bfi_ablk_h2i_optrom_s *m;
3337 
3338 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3339 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3340 		return BFA_STATUS_IOC_FAILURE;
3341 	}
3342 
3343 	if (ablk->busy) {
3344 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3345 		return  BFA_STATUS_DEVBUSY;
3346 	}
3347 
3348 	ablk->cbfn  = cbfn;
3349 	ablk->cbarg = cbarg;
3350 	ablk->busy  = BFA_TRUE;
3351 
3352 	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
3353 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_ENABLE,
3354 		bfa_ioc_portid(ablk->ioc));
3355 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3356 
3357 	return BFA_STATUS_OK;
3358 }
3359 
3360 bfa_status_t
3361 bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, bfa_ablk_cbfn_t cbfn, void *cbarg)
3362 {
3363 	struct bfi_ablk_h2i_optrom_s *m;
3364 
3365 	if (!bfa_ioc_is_operational(ablk->ioc)) {
3366 		bfa_trc(ablk->ioc, BFA_STATUS_IOC_FAILURE);
3367 		return BFA_STATUS_IOC_FAILURE;
3368 	}
3369 
3370 	if (ablk->busy) {
3371 		bfa_trc(ablk->ioc, BFA_STATUS_DEVBUSY);
3372 		return  BFA_STATUS_DEVBUSY;
3373 	}
3374 
3375 	ablk->cbfn  = cbfn;
3376 	ablk->cbarg = cbarg;
3377 	ablk->busy  = BFA_TRUE;
3378 
3379 	m = (struct bfi_ablk_h2i_optrom_s *)ablk->mb.msg;
3380 	bfi_h2i_set(m->mh, BFI_MC_ABLK, BFI_ABLK_H2I_OPTROM_DISABLE,
3381 		bfa_ioc_portid(ablk->ioc));
3382 	bfa_ioc_mbox_queue(ablk->ioc, &ablk->mb);
3383 
3384 	return BFA_STATUS_OK;
3385 }
3386 
3387 /*
3388  *	SFP module specific
3389  */
3390 
3391 /* forward declarations */
3392 static void bfa_sfp_getdata_send(struct bfa_sfp_s *sfp);
3393 static void bfa_sfp_media_get(struct bfa_sfp_s *sfp);
3394 static bfa_status_t bfa_sfp_speed_valid(struct bfa_sfp_s *sfp,
3395 				enum bfa_port_speed portspeed);
3396 
3397 static void
3398 bfa_cb_sfp_show(struct bfa_sfp_s *sfp)
3399 {
3400 	bfa_trc(sfp, sfp->lock);
3401 	if (sfp->cbfn)
3402 		sfp->cbfn(sfp->cbarg, sfp->status);
3403 	sfp->lock = 0;
3404 	sfp->cbfn = NULL;
3405 }
3406 
3407 static void
3408 bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp)
3409 {
3410 	bfa_trc(sfp, sfp->portspeed);
3411 	if (sfp->media) {
3412 		bfa_sfp_media_get(sfp);
3413 		if (sfp->state_query_cbfn)
3414 			sfp->state_query_cbfn(sfp->state_query_cbarg,
3415 					sfp->status);
3416 			sfp->media = NULL;
3417 		}
3418 
3419 		if (sfp->portspeed) {
3420 			sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed);
3421 			if (sfp->state_query_cbfn)
3422 				sfp->state_query_cbfn(sfp->state_query_cbarg,
3423 						sfp->status);
3424 				sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
3425 		}
3426 
3427 		sfp->state_query_lock = 0;
3428 		sfp->state_query_cbfn = NULL;
3429 }
3430 
3431 /*
3432  *	IOC event handler.
3433  */
3434 static void
3435 bfa_sfp_notify(void *sfp_arg, enum bfa_ioc_event_e event)
3436 {
3437 	struct bfa_sfp_s *sfp = sfp_arg;
3438 
3439 	bfa_trc(sfp, event);
3440 	bfa_trc(sfp, sfp->lock);
3441 	bfa_trc(sfp, sfp->state_query_lock);
3442 
3443 	switch (event) {
3444 	case BFA_IOC_E_DISABLED:
3445 	case BFA_IOC_E_FAILED:
3446 		if (sfp->lock) {
3447 			sfp->status = BFA_STATUS_IOC_FAILURE;
3448 			bfa_cb_sfp_show(sfp);
3449 		}
3450 
3451 		if (sfp->state_query_lock) {
3452 			sfp->status = BFA_STATUS_IOC_FAILURE;
3453 			bfa_cb_sfp_state_query(sfp);
3454 		}
3455 		break;
3456 
3457 	default:
3458 		break;
3459 	}
3460 }
3461 
3462 /*
3463  * SFP's State Change Notification post to AEN
3464  */
3465 static void
3466 bfa_sfp_scn_aen_post(struct bfa_sfp_s *sfp, struct bfi_sfp_scn_s *rsp)
3467 {
3468 	struct bfad_s *bfad = (struct bfad_s *)sfp->ioc->bfa->bfad;
3469 	struct bfa_aen_entry_s  *aen_entry;
3470 	enum bfa_port_aen_event aen_evt = 0;
3471 
3472 	bfa_trc(sfp, (((u64)rsp->pomlvl) << 16) | (((u64)rsp->sfpid) << 8) |
3473 		      ((u64)rsp->event));
3474 
3475 	bfad_get_aen_entry(bfad, aen_entry);
3476 	if (!aen_entry)
3477 		return;
3478 
3479 	aen_entry->aen_data.port.ioc_type = bfa_ioc_get_type(sfp->ioc);
3480 	aen_entry->aen_data.port.pwwn = sfp->ioc->attr->pwwn;
3481 	aen_entry->aen_data.port.mac = bfa_ioc_get_mac(sfp->ioc);
3482 
3483 	switch (rsp->event) {
3484 	case BFA_SFP_SCN_INSERTED:
3485 		aen_evt = BFA_PORT_AEN_SFP_INSERT;
3486 		break;
3487 	case BFA_SFP_SCN_REMOVED:
3488 		aen_evt = BFA_PORT_AEN_SFP_REMOVE;
3489 		break;
3490 	case BFA_SFP_SCN_FAILED:
3491 		aen_evt = BFA_PORT_AEN_SFP_ACCESS_ERROR;
3492 		break;
3493 	case BFA_SFP_SCN_UNSUPPORT:
3494 		aen_evt = BFA_PORT_AEN_SFP_UNSUPPORT;
3495 		break;
3496 	case BFA_SFP_SCN_POM:
3497 		aen_evt = BFA_PORT_AEN_SFP_POM;
3498 		aen_entry->aen_data.port.level = rsp->pomlvl;
3499 		break;
3500 	default:
3501 		bfa_trc(sfp, rsp->event);
3502 		WARN_ON(1);
3503 	}
3504 
3505 	/* Send the AEN notification */
3506 	bfad_im_post_vendor_event(aen_entry, bfad, ++sfp->ioc->ioc_aen_seq,
3507 				  BFA_AEN_CAT_PORT, aen_evt);
3508 }
3509 
3510 /*
3511  *	SFP get data send
3512  */
3513 static void
3514 bfa_sfp_getdata_send(struct bfa_sfp_s *sfp)
3515 {
3516 	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
3517 
3518 	bfa_trc(sfp, req->memtype);
3519 
3520 	/* build host command */
3521 	bfi_h2i_set(req->mh, BFI_MC_SFP, BFI_SFP_H2I_SHOW,
3522 			bfa_ioc_portid(sfp->ioc));
3523 
3524 	/* send mbox cmd */
3525 	bfa_ioc_mbox_queue(sfp->ioc, &sfp->mbcmd);
3526 }
3527 
3528 /*
3529  *	SFP is valid, read sfp data
3530  */
3531 static void
3532 bfa_sfp_getdata(struct bfa_sfp_s *sfp, enum bfi_sfp_mem_e memtype)
3533 {
3534 	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
3535 
3536 	WARN_ON(sfp->lock != 0);
3537 	bfa_trc(sfp, sfp->state);
3538 
3539 	sfp->lock = 1;
3540 	sfp->memtype = memtype;
3541 	req->memtype = memtype;
3542 
3543 	/* Setup SG list */
3544 	bfa_alen_set(&req->alen, sizeof(struct sfp_mem_s), sfp->dbuf_pa);
3545 
3546 	bfa_sfp_getdata_send(sfp);
3547 }
3548 
3549 /*
3550  *	SFP scn handler
3551  */
3552 static void
3553 bfa_sfp_scn(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
3554 {
3555 	struct bfi_sfp_scn_s *rsp = (struct bfi_sfp_scn_s *) msg;
3556 
3557 	switch (rsp->event) {
3558 	case BFA_SFP_SCN_INSERTED:
3559 		sfp->state = BFA_SFP_STATE_INSERTED;
3560 		sfp->data_valid = 0;
3561 		bfa_sfp_scn_aen_post(sfp, rsp);
3562 		break;
3563 	case BFA_SFP_SCN_REMOVED:
3564 		sfp->state = BFA_SFP_STATE_REMOVED;
3565 		sfp->data_valid = 0;
3566 		bfa_sfp_scn_aen_post(sfp, rsp);
3567 		 break;
3568 	case BFA_SFP_SCN_FAILED:
3569 		sfp->state = BFA_SFP_STATE_FAILED;
3570 		sfp->data_valid = 0;
3571 		bfa_sfp_scn_aen_post(sfp, rsp);
3572 		break;
3573 	case BFA_SFP_SCN_UNSUPPORT:
3574 		sfp->state = BFA_SFP_STATE_UNSUPPORT;
3575 		bfa_sfp_scn_aen_post(sfp, rsp);
3576 		if (!sfp->lock)
3577 			bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
3578 		break;
3579 	case BFA_SFP_SCN_POM:
3580 		bfa_sfp_scn_aen_post(sfp, rsp);
3581 		break;
3582 	case BFA_SFP_SCN_VALID:
3583 		sfp->state = BFA_SFP_STATE_VALID;
3584 		if (!sfp->lock)
3585 			bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
3586 		break;
3587 	default:
3588 		bfa_trc(sfp, rsp->event);
3589 		WARN_ON(1);
3590 	}
3591 }
3592 
3593 /*
3594  * SFP show complete
3595  */
3596 static void
3597 bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg)
3598 {
3599 	struct bfi_sfp_rsp_s *rsp = (struct bfi_sfp_rsp_s *) msg;
3600 
3601 	if (!sfp->lock) {
3602 		/*
3603 		 * receiving response after ioc failure
3604 		 */
3605 		bfa_trc(sfp, sfp->lock);
3606 		return;
3607 	}
3608 
3609 	bfa_trc(sfp, rsp->status);
3610 	if (rsp->status == BFA_STATUS_OK) {
3611 		sfp->data_valid = 1;
3612 		if (sfp->state == BFA_SFP_STATE_VALID)
3613 			sfp->status = BFA_STATUS_OK;
3614 		else if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
3615 			sfp->status = BFA_STATUS_SFP_UNSUPP;
3616 		else
3617 			bfa_trc(sfp, sfp->state);
3618 	} else {
3619 		sfp->data_valid = 0;
3620 		sfp->status = rsp->status;
3621 		/* sfpshow shouldn't change sfp state */
3622 	}
3623 
3624 	bfa_trc(sfp, sfp->memtype);
3625 	if (sfp->memtype == BFI_SFP_MEM_DIAGEXT) {
3626 		bfa_trc(sfp, sfp->data_valid);
3627 		if (sfp->data_valid) {
3628 			u32	size = sizeof(struct sfp_mem_s);
3629 			u8 *des = (u8 *) &(sfp->sfpmem->srlid_base);
3630 			memcpy(des, sfp->dbuf_kva, size);
3631 		}
3632 		/*
3633 		 * Queue completion callback.
3634 		 */
3635 		bfa_cb_sfp_show(sfp);
3636 	} else
3637 		sfp->lock = 0;
3638 
3639 	bfa_trc(sfp, sfp->state_query_lock);
3640 	if (sfp->state_query_lock) {
3641 		sfp->state = rsp->state;
3642 		/* Complete callback */
3643 		bfa_cb_sfp_state_query(sfp);
3644 	}
3645 }
3646 
3647 /*
3648  *	SFP query fw sfp state
3649  */
3650 static void
3651 bfa_sfp_state_query(struct bfa_sfp_s *sfp)
3652 {
3653 	struct bfi_sfp_req_s *req = (struct bfi_sfp_req_s *)sfp->mbcmd.msg;
3654 
3655 	/* Should not be doing query if not in _INIT state */
3656 	WARN_ON(sfp->state != BFA_SFP_STATE_INIT);
3657 	WARN_ON(sfp->state_query_lock != 0);
3658 	bfa_trc(sfp, sfp->state);
3659 
3660 	sfp->state_query_lock = 1;
3661 	req->memtype = 0;
3662 
3663 	if (!sfp->lock)
3664 		bfa_sfp_getdata(sfp, BFI_SFP_MEM_ALL);
3665 }
3666 
3667 static void
3668 bfa_sfp_media_get(struct bfa_sfp_s *sfp)
3669 {
3670 	enum bfa_defs_sfp_media_e *media = sfp->media;
3671 
3672 	*media = BFA_SFP_MEDIA_UNKNOWN;
3673 
3674 	if (sfp->state == BFA_SFP_STATE_UNSUPPORT)
3675 		*media = BFA_SFP_MEDIA_UNSUPPORT;
3676 	else if (sfp->state == BFA_SFP_STATE_VALID) {
3677 		union sfp_xcvr_e10g_code_u e10g;
3678 		struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
3679 		u16 xmtr_tech = (sfpmem->srlid_base.xcvr[4] & 0x3) << 7 |
3680 				(sfpmem->srlid_base.xcvr[5] >> 1);
3681 
3682 		e10g.b = sfpmem->srlid_base.xcvr[0];
3683 		bfa_trc(sfp, e10g.b);
3684 		bfa_trc(sfp, xmtr_tech);
3685 		/* check fc transmitter tech */
3686 		if ((xmtr_tech & SFP_XMTR_TECH_CU) ||
3687 		    (xmtr_tech & SFP_XMTR_TECH_CP) ||
3688 		    (xmtr_tech & SFP_XMTR_TECH_CA))
3689 			*media = BFA_SFP_MEDIA_CU;
3690 		else if ((xmtr_tech & SFP_XMTR_TECH_EL_INTRA) ||
3691 			 (xmtr_tech & SFP_XMTR_TECH_EL_INTER))
3692 			*media = BFA_SFP_MEDIA_EL;
3693 		else if ((xmtr_tech & SFP_XMTR_TECH_LL) ||
3694 			 (xmtr_tech & SFP_XMTR_TECH_LC))
3695 			*media = BFA_SFP_MEDIA_LW;
3696 		else if ((xmtr_tech & SFP_XMTR_TECH_SL) ||
3697 			 (xmtr_tech & SFP_XMTR_TECH_SN) ||
3698 			 (xmtr_tech & SFP_XMTR_TECH_SA))
3699 			*media = BFA_SFP_MEDIA_SW;
3700 		/* Check 10G Ethernet Compilance code */
3701 		else if (e10g.r.e10g_sr)
3702 			*media = BFA_SFP_MEDIA_SW;
3703 		else if (e10g.r.e10g_lrm && e10g.r.e10g_lr)
3704 			*media = BFA_SFP_MEDIA_LW;
3705 		else if (e10g.r.e10g_unall)
3706 			*media = BFA_SFP_MEDIA_UNKNOWN;
3707 		else
3708 			bfa_trc(sfp, 0);
3709 	} else
3710 		bfa_trc(sfp, sfp->state);
3711 }
3712 
3713 static bfa_status_t
3714 bfa_sfp_speed_valid(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed)
3715 {
3716 	struct sfp_mem_s *sfpmem = (struct sfp_mem_s *)sfp->dbuf_kva;
3717 	struct sfp_xcvr_s *xcvr = (struct sfp_xcvr_s *) sfpmem->srlid_base.xcvr;
3718 	union sfp_xcvr_fc3_code_u fc3 = xcvr->fc3;
3719 	union sfp_xcvr_e10g_code_u e10g = xcvr->e10g;
3720 
3721 	if (portspeed == BFA_PORT_SPEED_10GBPS) {
3722 		if (e10g.r.e10g_sr || e10g.r.e10g_lr)
3723 			return BFA_STATUS_OK;
3724 		else {
3725 			bfa_trc(sfp, e10g.b);
3726 			return BFA_STATUS_UNSUPP_SPEED;
3727 		}
3728 	}
3729 	if (((portspeed & BFA_PORT_SPEED_16GBPS) && fc3.r.mb1600) ||
3730 	    ((portspeed & BFA_PORT_SPEED_8GBPS) && fc3.r.mb800) ||
3731 	    ((portspeed & BFA_PORT_SPEED_4GBPS) && fc3.r.mb400) ||
3732 	    ((portspeed & BFA_PORT_SPEED_2GBPS) && fc3.r.mb200) ||
3733 	    ((portspeed & BFA_PORT_SPEED_1GBPS) && fc3.r.mb100))
3734 		return BFA_STATUS_OK;
3735 	else {
3736 		bfa_trc(sfp, portspeed);
3737 		bfa_trc(sfp, fc3.b);
3738 		bfa_trc(sfp, e10g.b);
3739 		return BFA_STATUS_UNSUPP_SPEED;
3740 	}
3741 }
3742 
3743 /*
3744  *	SFP hmbox handler
3745  */
3746 void
3747 bfa_sfp_intr(void *sfparg, struct bfi_mbmsg_s *msg)
3748 {
3749 	struct bfa_sfp_s *sfp = sfparg;
3750 
3751 	switch (msg->mh.msg_id) {
3752 	case BFI_SFP_I2H_SHOW:
3753 		bfa_sfp_show_comp(sfp, msg);
3754 		break;
3755 
3756 	case BFI_SFP_I2H_SCN:
3757 		bfa_sfp_scn(sfp, msg);
3758 		break;
3759 
3760 	default:
3761 		bfa_trc(sfp, msg->mh.msg_id);
3762 		WARN_ON(1);
3763 	}
3764 }
3765 
3766 /*
3767  *	Return DMA memory needed by sfp module.
3768  */
3769 u32
3770 bfa_sfp_meminfo(void)
3771 {
3772 	return BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
3773 }
3774 
3775 /*
3776  *	Attach virtual and physical memory for SFP.
3777  */
3778 void
3779 bfa_sfp_attach(struct bfa_sfp_s *sfp, struct bfa_ioc_s *ioc, void *dev,
3780 		struct bfa_trc_mod_s *trcmod)
3781 {
3782 	sfp->dev = dev;
3783 	sfp->ioc = ioc;
3784 	sfp->trcmod = trcmod;
3785 
3786 	sfp->cbfn = NULL;
3787 	sfp->cbarg = NULL;
3788 	sfp->sfpmem = NULL;
3789 	sfp->lock = 0;
3790 	sfp->data_valid = 0;
3791 	sfp->state = BFA_SFP_STATE_INIT;
3792 	sfp->state_query_lock = 0;
3793 	sfp->state_query_cbfn = NULL;
3794 	sfp->state_query_cbarg = NULL;
3795 	sfp->media = NULL;
3796 	sfp->portspeed = BFA_PORT_SPEED_UNKNOWN;
3797 	sfp->is_elb = BFA_FALSE;
3798 
3799 	bfa_ioc_mbox_regisr(sfp->ioc, BFI_MC_SFP, bfa_sfp_intr, sfp);
3800 	bfa_q_qe_init(&sfp->ioc_notify);
3801 	bfa_ioc_notify_init(&sfp->ioc_notify, bfa_sfp_notify, sfp);
3802 	list_add_tail(&sfp->ioc_notify.qe, &sfp->ioc->notify_q);
3803 }
3804 
3805 /*
3806  *	Claim Memory for SFP
3807  */
3808 void
3809 bfa_sfp_memclaim(struct bfa_sfp_s *sfp, u8 *dm_kva, u64 dm_pa)
3810 {
3811 	sfp->dbuf_kva   = dm_kva;
3812 	sfp->dbuf_pa    = dm_pa;
3813 	memset(sfp->dbuf_kva, 0, sizeof(struct sfp_mem_s));
3814 
3815 	dm_kva += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
3816 	dm_pa += BFA_ROUNDUP(sizeof(struct sfp_mem_s), BFA_DMA_ALIGN_SZ);
3817 }
3818 
3819 /*
3820  * Show SFP eeprom content
3821  *
3822  * @param[in] sfp   - bfa sfp module
3823  *
3824  * @param[out] sfpmem - sfp eeprom data
3825  *
3826  */
3827 bfa_status_t
3828 bfa_sfp_show(struct bfa_sfp_s *sfp, struct sfp_mem_s *sfpmem,
3829 		bfa_cb_sfp_t cbfn, void *cbarg)
3830 {
3831 
3832 	if (!bfa_ioc_is_operational(sfp->ioc)) {
3833 		bfa_trc(sfp, 0);
3834 		return BFA_STATUS_IOC_NON_OP;
3835 	}
3836 
3837 	if (sfp->lock) {
3838 		bfa_trc(sfp, 0);
3839 		return BFA_STATUS_DEVBUSY;
3840 	}
3841 
3842 	sfp->cbfn = cbfn;
3843 	sfp->cbarg = cbarg;
3844 	sfp->sfpmem = sfpmem;
3845 
3846 	bfa_sfp_getdata(sfp, BFI_SFP_MEM_DIAGEXT);
3847 	return BFA_STATUS_OK;
3848 }
3849 
3850 /*
3851  * Return SFP Media type
3852  *
3853  * @param[in] sfp   - bfa sfp module
3854  *
3855  * @param[out] media - port speed from user
3856  *
3857  */
3858 bfa_status_t
3859 bfa_sfp_media(struct bfa_sfp_s *sfp, enum bfa_defs_sfp_media_e *media,
3860 		bfa_cb_sfp_t cbfn, void *cbarg)
3861 {
3862 	if (!bfa_ioc_is_operational(sfp->ioc)) {
3863 		bfa_trc(sfp, 0);
3864 		return BFA_STATUS_IOC_NON_OP;
3865 	}
3866 
3867 	sfp->media = media;
3868 	if (sfp->state == BFA_SFP_STATE_INIT) {
3869 		if (sfp->state_query_lock) {
3870 			bfa_trc(sfp, 0);
3871 			return BFA_STATUS_DEVBUSY;
3872 		} else {
3873 			sfp->state_query_cbfn = cbfn;
3874 			sfp->state_query_cbarg = cbarg;
3875 			bfa_sfp_state_query(sfp);
3876 			return BFA_STATUS_SFP_NOT_READY;
3877 		}
3878 	}
3879 
3880 	bfa_sfp_media_get(sfp);
3881 	return BFA_STATUS_OK;
3882 }
3883 
3884 /*
3885  * Check if user set port speed is allowed by the SFP
3886  *
3887  * @param[in] sfp   - bfa sfp module
3888  * @param[in] portspeed - port speed from user
3889  *
3890  */
3891 bfa_status_t
3892 bfa_sfp_speed(struct bfa_sfp_s *sfp, enum bfa_port_speed portspeed,
3893 		bfa_cb_sfp_t cbfn, void *cbarg)
3894 {
3895 	WARN_ON(portspeed == BFA_PORT_SPEED_UNKNOWN);
3896 
3897 	if (!bfa_ioc_is_operational(sfp->ioc))
3898 		return BFA_STATUS_IOC_NON_OP;
3899 
3900 	/* For Mezz card, all speed is allowed */
3901 	if (bfa_mfg_is_mezz(sfp->ioc->attr->card_type))
3902 		return BFA_STATUS_OK;
3903 
3904 	/* Check SFP state */
3905 	sfp->portspeed = portspeed;
3906 	if (sfp->state == BFA_SFP_STATE_INIT) {
3907 		if (sfp->state_query_lock) {
3908 			bfa_trc(sfp, 0);
3909 			return BFA_STATUS_DEVBUSY;
3910 		} else {
3911 			sfp->state_query_cbfn = cbfn;
3912 			sfp->state_query_cbarg = cbarg;
3913 			bfa_sfp_state_query(sfp);
3914 			return BFA_STATUS_SFP_NOT_READY;
3915 		}
3916 	}
3917 
3918 	if (sfp->state == BFA_SFP_STATE_REMOVED ||
3919 	    sfp->state == BFA_SFP_STATE_FAILED) {
3920 		bfa_trc(sfp, sfp->state);
3921 		return BFA_STATUS_NO_SFP_DEV;
3922 	}
3923 
3924 	if (sfp->state == BFA_SFP_STATE_INSERTED) {
3925 		bfa_trc(sfp, sfp->state);
3926 		return BFA_STATUS_DEVBUSY;  /* sfp is reading data */
3927 	}
3928 
3929 	/* For eloopback, all speed is allowed */
3930 	if (sfp->is_elb)
3931 		return BFA_STATUS_OK;
3932 
3933 	return bfa_sfp_speed_valid(sfp, portspeed);
3934 }
3935 
3936 /*
3937  *	Flash module specific
3938  */
3939 
3940 /*
3941  * FLASH DMA buffer should be big enough to hold both MFG block and
3942  * asic block(64k) at the same time and also should be 2k aligned to
3943  * avoid write segement to cross sector boundary.
3944  */
3945 #define BFA_FLASH_SEG_SZ	2048
3946 #define BFA_FLASH_DMA_BUF_SZ	\
3947 	BFA_ROUNDUP(0x010000 + sizeof(struct bfa_mfg_block_s), BFA_FLASH_SEG_SZ)
3948 
3949 static void
3950 bfa_flash_aen_audit_post(struct bfa_ioc_s *ioc, enum bfa_audit_aen_event event,
3951 			int inst, int type)
3952 {
3953 	struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
3954 	struct bfa_aen_entry_s  *aen_entry;
3955 
3956 	bfad_get_aen_entry(bfad, aen_entry);
3957 	if (!aen_entry)
3958 		return;
3959 
3960 	aen_entry->aen_data.audit.pwwn = ioc->attr->pwwn;
3961 	aen_entry->aen_data.audit.partition_inst = inst;
3962 	aen_entry->aen_data.audit.partition_type = type;
3963 
3964 	/* Send the AEN notification */
3965 	bfad_im_post_vendor_event(aen_entry, bfad, ++ioc->ioc_aen_seq,
3966 				  BFA_AEN_CAT_AUDIT, event);
3967 }
3968 
3969 static void
3970 bfa_flash_cb(struct bfa_flash_s *flash)
3971 {
3972 	flash->op_busy = 0;
3973 	if (flash->cbfn)
3974 		flash->cbfn(flash->cbarg, flash->status);
3975 }
3976 
3977 static void
3978 bfa_flash_notify(void *cbarg, enum bfa_ioc_event_e event)
3979 {
3980 	struct bfa_flash_s	*flash = cbarg;
3981 
3982 	bfa_trc(flash, event);
3983 	switch (event) {
3984 	case BFA_IOC_E_DISABLED:
3985 	case BFA_IOC_E_FAILED:
3986 		if (flash->op_busy) {
3987 			flash->status = BFA_STATUS_IOC_FAILURE;
3988 			flash->cbfn(flash->cbarg, flash->status);
3989 			flash->op_busy = 0;
3990 		}
3991 		break;
3992 
3993 	default:
3994 		break;
3995 	}
3996 }
3997 
3998 /*
3999  * Send flash attribute query request.
4000  *
4001  * @param[in] cbarg - callback argument
4002  */
4003 static void
4004 bfa_flash_query_send(void *cbarg)
4005 {
4006 	struct bfa_flash_s *flash = cbarg;
4007 	struct bfi_flash_query_req_s *msg =
4008 			(struct bfi_flash_query_req_s *) flash->mb.msg;
4009 
4010 	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
4011 		bfa_ioc_portid(flash->ioc));
4012 	bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr_s),
4013 		flash->dbuf_pa);
4014 	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4015 }
4016 
4017 /*
4018  * Send flash write request.
4019  *
4020  * @param[in] cbarg - callback argument
4021  */
4022 static void
4023 bfa_flash_write_send(struct bfa_flash_s *flash)
4024 {
4025 	struct bfi_flash_write_req_s *msg =
4026 			(struct bfi_flash_write_req_s *) flash->mb.msg;
4027 	u32	len;
4028 
4029 	msg->type = be32_to_cpu(flash->type);
4030 	msg->instance = flash->instance;
4031 	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
4032 	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
4033 		flash->residue : BFA_FLASH_DMA_BUF_SZ;
4034 	msg->length = be32_to_cpu(len);
4035 
4036 	/* indicate if it's the last msg of the whole write operation */
4037 	msg->last = (len == flash->residue) ? 1 : 0;
4038 
4039 	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
4040 			bfa_ioc_portid(flash->ioc));
4041 	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
4042 	memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
4043 	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4044 
4045 	flash->residue -= len;
4046 	flash->offset += len;
4047 }
4048 
4049 /*
4050  * Send flash read request.
4051  *
4052  * @param[in] cbarg - callback argument
4053  */
4054 static void
4055 bfa_flash_read_send(void *cbarg)
4056 {
4057 	struct bfa_flash_s *flash = cbarg;
4058 	struct bfi_flash_read_req_s *msg =
4059 			(struct bfi_flash_read_req_s *) flash->mb.msg;
4060 	u32	len;
4061 
4062 	msg->type = be32_to_cpu(flash->type);
4063 	msg->instance = flash->instance;
4064 	msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
4065 	len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
4066 			flash->residue : BFA_FLASH_DMA_BUF_SZ;
4067 	msg->length = be32_to_cpu(len);
4068 	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
4069 		bfa_ioc_portid(flash->ioc));
4070 	bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
4071 	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4072 }
4073 
4074 /*
4075  * Send flash erase request.
4076  *
4077  * @param[in] cbarg - callback argument
4078  */
4079 static void
4080 bfa_flash_erase_send(void *cbarg)
4081 {
4082 	struct bfa_flash_s *flash = cbarg;
4083 	struct bfi_flash_erase_req_s *msg =
4084 			(struct bfi_flash_erase_req_s *) flash->mb.msg;
4085 
4086 	msg->type = be32_to_cpu(flash->type);
4087 	msg->instance = flash->instance;
4088 	bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_ERASE_REQ,
4089 			bfa_ioc_portid(flash->ioc));
4090 	bfa_ioc_mbox_queue(flash->ioc, &flash->mb);
4091 }
4092 
4093 /*
4094  * Process flash response messages upon receiving interrupts.
4095  *
4096  * @param[in] flasharg - flash structure
4097  * @param[in] msg - message structure
4098  */
4099 static void
4100 bfa_flash_intr(void *flasharg, struct bfi_mbmsg_s *msg)
4101 {
4102 	struct bfa_flash_s *flash = flasharg;
4103 	u32	status;
4104 
4105 	union {
4106 		struct bfi_flash_query_rsp_s *query;
4107 		struct bfi_flash_erase_rsp_s *erase;
4108 		struct bfi_flash_write_rsp_s *write;
4109 		struct bfi_flash_read_rsp_s *read;
4110 		struct bfi_flash_event_s *event;
4111 		struct bfi_mbmsg_s   *msg;
4112 	} m;
4113 
4114 	m.msg = msg;
4115 	bfa_trc(flash, msg->mh.msg_id);
4116 
4117 	if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT) {
4118 		/* receiving response after ioc failure */
4119 		bfa_trc(flash, 0x9999);
4120 		return;
4121 	}
4122 
4123 	switch (msg->mh.msg_id) {
4124 	case BFI_FLASH_I2H_QUERY_RSP:
4125 		status = be32_to_cpu(m.query->status);
4126 		bfa_trc(flash, status);
4127 		if (status == BFA_STATUS_OK) {
4128 			u32	i;
4129 			struct bfa_flash_attr_s *attr, *f;
4130 
4131 			attr = (struct bfa_flash_attr_s *) flash->ubuf;
4132 			f = (struct bfa_flash_attr_s *) flash->dbuf_kva;
4133 			attr->status = be32_to_cpu(f->status);
4134 			attr->npart = be32_to_cpu(f->npart);
4135 			bfa_trc(flash, attr->status);
4136 			bfa_trc(flash, attr->npart);
4137 			for (i = 0; i < attr->npart; i++) {
4138 				attr->part[i].part_type =
4139 					be32_to_cpu(f->part[i].part_type);
4140 				attr->part[i].part_instance =
4141 					be32_to_cpu(f->part[i].part_instance);
4142 				attr->part[i].part_off =
4143 					be32_to_cpu(f->part[i].part_off);
4144 				attr->part[i].part_size =
4145 					be32_to_cpu(f->part[i].part_size);
4146 				attr->part[i].part_len =
4147 					be32_to_cpu(f->part[i].part_len);
4148 				attr->part[i].part_status =
4149 					be32_to_cpu(f->part[i].part_status);
4150 			}
4151 		}
4152 		flash->status = status;
4153 		bfa_flash_cb(flash);
4154 		break;
4155 	case BFI_FLASH_I2H_ERASE_RSP:
4156 		status = be32_to_cpu(m.erase->status);
4157 		bfa_trc(flash, status);
4158 		flash->status = status;
4159 		bfa_flash_cb(flash);
4160 		break;
4161 	case BFI_FLASH_I2H_WRITE_RSP:
4162 		status = be32_to_cpu(m.write->status);
4163 		bfa_trc(flash, status);
4164 		if (status != BFA_STATUS_OK || flash->residue == 0) {
4165 			flash->status = status;
4166 			bfa_flash_cb(flash);
4167 		} else {
4168 			bfa_trc(flash, flash->offset);
4169 			bfa_flash_write_send(flash);
4170 		}
4171 		break;
4172 	case BFI_FLASH_I2H_READ_RSP:
4173 		status = be32_to_cpu(m.read->status);
4174 		bfa_trc(flash, status);
4175 		if (status != BFA_STATUS_OK) {
4176 			flash->status = status;
4177 			bfa_flash_cb(flash);
4178 		} else {
4179 			u32 len = be32_to_cpu(m.read->length);
4180 			bfa_trc(flash, flash->offset);
4181 			bfa_trc(flash, len);
4182 			memcpy(flash->ubuf + flash->offset,
4183 				flash->dbuf_kva, len);
4184 			flash->residue -= len;
4185 			flash->offset += len;
4186 			if (flash->residue == 0) {
4187 				flash->status = status;
4188 				bfa_flash_cb(flash);
4189 			} else
4190 				bfa_flash_read_send(flash);
4191 		}
4192 		break;
4193 	case BFI_FLASH_I2H_BOOT_VER_RSP:
4194 		break;
4195 	case BFI_FLASH_I2H_EVENT:
4196 		status = be32_to_cpu(m.event->status);
4197 		bfa_trc(flash, status);
4198 		if (status == BFA_STATUS_BAD_FWCFG)
4199 			bfa_ioc_aen_post(flash->ioc, BFA_IOC_AEN_FWCFG_ERROR);
4200 		else if (status == BFA_STATUS_INVALID_VENDOR) {
4201 			u32 param;
4202 			param = be32_to_cpu(m.event->param);
4203 			bfa_trc(flash, param);
4204 			bfa_ioc_aen_post(flash->ioc,
4205 				BFA_IOC_AEN_INVALID_VENDOR);
4206 		}
4207 		break;
4208 
4209 	default:
4210 		WARN_ON(1);
4211 	}
4212 }
4213 
4214 /*
4215  * Flash memory info API.
4216  *
4217  * @param[in] mincfg - minimal cfg variable
4218  */
4219 u32
4220 bfa_flash_meminfo(bfa_boolean_t mincfg)
4221 {
4222 	/* min driver doesn't need flash */
4223 	if (mincfg)
4224 		return 0;
4225 	return BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4226 }
4227 
4228 /*
4229  * Flash attach API.
4230  *
4231  * @param[in] flash - flash structure
4232  * @param[in] ioc  - ioc structure
4233  * @param[in] dev  - device structure
4234  * @param[in] trcmod - trace module
4235  * @param[in] logmod - log module
4236  */
4237 void
4238 bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc, void *dev,
4239 		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
4240 {
4241 	flash->ioc = ioc;
4242 	flash->trcmod = trcmod;
4243 	flash->cbfn = NULL;
4244 	flash->cbarg = NULL;
4245 	flash->op_busy = 0;
4246 
4247 	bfa_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
4248 	bfa_q_qe_init(&flash->ioc_notify);
4249 	bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
4250 	list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);
4251 
4252 	/* min driver doesn't need flash */
4253 	if (mincfg) {
4254 		flash->dbuf_kva = NULL;
4255 		flash->dbuf_pa = 0;
4256 	}
4257 }
4258 
4259 /*
4260  * Claim memory for flash
4261  *
4262  * @param[in] flash - flash structure
4263  * @param[in] dm_kva - pointer to virtual memory address
4264  * @param[in] dm_pa - physical memory address
4265  * @param[in] mincfg - minimal cfg variable
4266  */
4267 void
4268 bfa_flash_memclaim(struct bfa_flash_s *flash, u8 *dm_kva, u64 dm_pa,
4269 		bfa_boolean_t mincfg)
4270 {
4271 	if (mincfg)
4272 		return;
4273 
4274 	flash->dbuf_kva = dm_kva;
4275 	flash->dbuf_pa = dm_pa;
4276 	memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
4277 	dm_kva += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4278 	dm_pa += BFA_ROUNDUP(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
4279 }
4280 
4281 /*
4282  * Get flash attribute.
4283  *
4284  * @param[in] flash - flash structure
4285  * @param[in] attr - flash attribute structure
4286  * @param[in] cbfn - callback function
4287  * @param[in] cbarg - callback argument
4288  *
4289  * Return status.
4290  */
4291 bfa_status_t
4292 bfa_flash_get_attr(struct bfa_flash_s *flash, struct bfa_flash_attr_s *attr,
4293 		bfa_cb_flash_t cbfn, void *cbarg)
4294 {
4295 	bfa_trc(flash, BFI_FLASH_H2I_QUERY_REQ);
4296 
4297 	if (!bfa_ioc_is_operational(flash->ioc))
4298 		return BFA_STATUS_IOC_NON_OP;
4299 
4300 	if (flash->op_busy) {
4301 		bfa_trc(flash, flash->op_busy);
4302 		return BFA_STATUS_DEVBUSY;
4303 	}
4304 
4305 	flash->op_busy = 1;
4306 	flash->cbfn = cbfn;
4307 	flash->cbarg = cbarg;
4308 	flash->ubuf = (u8 *) attr;
4309 	bfa_flash_query_send(flash);
4310 
4311 	return BFA_STATUS_OK;
4312 }
4313 
4314 /*
4315  * Erase flash partition.
4316  *
4317  * @param[in] flash - flash structure
4318  * @param[in] type - flash partition type
4319  * @param[in] instance - flash partition instance
4320  * @param[in] cbfn - callback function
4321  * @param[in] cbarg - callback argument
4322  *
4323  * Return status.
4324  */
4325 bfa_status_t
4326 bfa_flash_erase_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4327 		u8 instance, bfa_cb_flash_t cbfn, void *cbarg)
4328 {
4329 	bfa_trc(flash, BFI_FLASH_H2I_ERASE_REQ);
4330 	bfa_trc(flash, type);
4331 	bfa_trc(flash, instance);
4332 
4333 	if (!bfa_ioc_is_operational(flash->ioc))
4334 		return BFA_STATUS_IOC_NON_OP;
4335 
4336 	if (flash->op_busy) {
4337 		bfa_trc(flash, flash->op_busy);
4338 		return BFA_STATUS_DEVBUSY;
4339 	}
4340 
4341 	flash->op_busy = 1;
4342 	flash->cbfn = cbfn;
4343 	flash->cbarg = cbarg;
4344 	flash->type = type;
4345 	flash->instance = instance;
4346 
4347 	bfa_flash_erase_send(flash);
4348 	bfa_flash_aen_audit_post(flash->ioc, BFA_AUDIT_AEN_FLASH_ERASE,
4349 				instance, type);
4350 	return BFA_STATUS_OK;
4351 }
4352 
4353 /*
4354  * Update flash partition.
4355  *
4356  * @param[in] flash - flash structure
4357  * @param[in] type - flash partition type
4358  * @param[in] instance - flash partition instance
4359  * @param[in] buf - update data buffer
4360  * @param[in] len - data buffer length
4361  * @param[in] offset - offset relative to the partition starting address
4362  * @param[in] cbfn - callback function
4363  * @param[in] cbarg - callback argument
4364  *
4365  * Return status.
4366  */
4367 bfa_status_t
4368 bfa_flash_update_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4369 		u8 instance, void *buf, u32 len, u32 offset,
4370 		bfa_cb_flash_t cbfn, void *cbarg)
4371 {
4372 	bfa_trc(flash, BFI_FLASH_H2I_WRITE_REQ);
4373 	bfa_trc(flash, type);
4374 	bfa_trc(flash, instance);
4375 	bfa_trc(flash, len);
4376 	bfa_trc(flash, offset);
4377 
4378 	if (!bfa_ioc_is_operational(flash->ioc))
4379 		return BFA_STATUS_IOC_NON_OP;
4380 
4381 	/*
4382 	 * 'len' must be in word (4-byte) boundary
4383 	 * 'offset' must be in sector (16kb) boundary
4384 	 */
4385 	if (!len || (len & 0x03) || (offset & 0x00003FFF))
4386 		return BFA_STATUS_FLASH_BAD_LEN;
4387 
4388 	if (type == BFA_FLASH_PART_MFG)
4389 		return BFA_STATUS_EINVAL;
4390 
4391 	if (flash->op_busy) {
4392 		bfa_trc(flash, flash->op_busy);
4393 		return BFA_STATUS_DEVBUSY;
4394 	}
4395 
4396 	flash->op_busy = 1;
4397 	flash->cbfn = cbfn;
4398 	flash->cbarg = cbarg;
4399 	flash->type = type;
4400 	flash->instance = instance;
4401 	flash->residue = len;
4402 	flash->offset = 0;
4403 	flash->addr_off = offset;
4404 	flash->ubuf = buf;
4405 
4406 	bfa_flash_write_send(flash);
4407 	return BFA_STATUS_OK;
4408 }
4409 
4410 /*
4411  * Read flash partition.
4412  *
4413  * @param[in] flash - flash structure
4414  * @param[in] type - flash partition type
4415  * @param[in] instance - flash partition instance
4416  * @param[in] buf - read data buffer
4417  * @param[in] len - data buffer length
4418  * @param[in] offset - offset relative to the partition starting address
4419  * @param[in] cbfn - callback function
4420  * @param[in] cbarg - callback argument
4421  *
4422  * Return status.
4423  */
4424 bfa_status_t
4425 bfa_flash_read_part(struct bfa_flash_s *flash, enum bfa_flash_part_type type,
4426 		u8 instance, void *buf, u32 len, u32 offset,
4427 		bfa_cb_flash_t cbfn, void *cbarg)
4428 {
4429 	bfa_trc(flash, BFI_FLASH_H2I_READ_REQ);
4430 	bfa_trc(flash, type);
4431 	bfa_trc(flash, instance);
4432 	bfa_trc(flash, len);
4433 	bfa_trc(flash, offset);
4434 
4435 	if (!bfa_ioc_is_operational(flash->ioc))
4436 		return BFA_STATUS_IOC_NON_OP;
4437 
4438 	/*
4439 	 * 'len' must be in word (4-byte) boundary
4440 	 * 'offset' must be in sector (16kb) boundary
4441 	 */
4442 	if (!len || (len & 0x03) || (offset & 0x00003FFF))
4443 		return BFA_STATUS_FLASH_BAD_LEN;
4444 
4445 	if (flash->op_busy) {
4446 		bfa_trc(flash, flash->op_busy);
4447 		return BFA_STATUS_DEVBUSY;
4448 	}
4449 
4450 	flash->op_busy = 1;
4451 	flash->cbfn = cbfn;
4452 	flash->cbarg = cbarg;
4453 	flash->type = type;
4454 	flash->instance = instance;
4455 	flash->residue = len;
4456 	flash->offset = 0;
4457 	flash->addr_off = offset;
4458 	flash->ubuf = buf;
4459 	bfa_flash_read_send(flash);
4460 
4461 	return BFA_STATUS_OK;
4462 }
4463 
4464 /*
4465  *	DIAG module specific
4466  */
4467 
4468 #define BFA_DIAG_MEMTEST_TOV	50000	/* memtest timeout in msec */
4469 #define CT2_BFA_DIAG_MEMTEST_TOV	(9*30*1000)  /* 4.5 min */
4470 
4471 /* IOC event handler */
4472 static void
4473 bfa_diag_notify(void *diag_arg, enum bfa_ioc_event_e event)
4474 {
4475 	struct bfa_diag_s *diag = diag_arg;
4476 
4477 	bfa_trc(diag, event);
4478 	bfa_trc(diag, diag->block);
4479 	bfa_trc(diag, diag->fwping.lock);
4480 	bfa_trc(diag, diag->tsensor.lock);
4481 
4482 	switch (event) {
4483 	case BFA_IOC_E_DISABLED:
4484 	case BFA_IOC_E_FAILED:
4485 		if (diag->fwping.lock) {
4486 			diag->fwping.status = BFA_STATUS_IOC_FAILURE;
4487 			diag->fwping.cbfn(diag->fwping.cbarg,
4488 					diag->fwping.status);
4489 			diag->fwping.lock = 0;
4490 		}
4491 
4492 		if (diag->tsensor.lock) {
4493 			diag->tsensor.status = BFA_STATUS_IOC_FAILURE;
4494 			diag->tsensor.cbfn(diag->tsensor.cbarg,
4495 					   diag->tsensor.status);
4496 			diag->tsensor.lock = 0;
4497 		}
4498 
4499 		if (diag->block) {
4500 			if (diag->timer_active) {
4501 				bfa_timer_stop(&diag->timer);
4502 				diag->timer_active = 0;
4503 			}
4504 
4505 			diag->status = BFA_STATUS_IOC_FAILURE;
4506 			diag->cbfn(diag->cbarg, diag->status);
4507 			diag->block = 0;
4508 		}
4509 		break;
4510 
4511 	default:
4512 		break;
4513 	}
4514 }
4515 
4516 static void
4517 bfa_diag_memtest_done(void *cbarg)
4518 {
4519 	struct bfa_diag_s *diag = cbarg;
4520 	struct bfa_ioc_s  *ioc = diag->ioc;
4521 	struct bfa_diag_memtest_result *res = diag->result;
4522 	u32	loff = BFI_BOOT_MEMTEST_RES_ADDR;
4523 	u32	pgnum, pgoff, i;
4524 
4525 	pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
4526 	pgoff = PSS_SMEM_PGOFF(loff);
4527 
4528 	writel(pgnum, ioc->ioc_regs.host_page_num_fn);
4529 
4530 	for (i = 0; i < (sizeof(struct bfa_diag_memtest_result) /
4531 			 sizeof(u32)); i++) {
4532 		/* read test result from smem */
4533 		*((u32 *) res + i) =
4534 			bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
4535 		loff += sizeof(u32);
4536 	}
4537 
4538 	/* Reset IOC fwstates to BFI_IOC_UNINIT */
4539 	bfa_ioc_reset_fwstate(ioc);
4540 
4541 	res->status = swab32(res->status);
4542 	bfa_trc(diag, res->status);
4543 
4544 	if (res->status == BFI_BOOT_MEMTEST_RES_SIG)
4545 		diag->status = BFA_STATUS_OK;
4546 	else {
4547 		diag->status = BFA_STATUS_MEMTEST_FAILED;
4548 		res->addr = swab32(res->addr);
4549 		res->exp = swab32(res->exp);
4550 		res->act = swab32(res->act);
4551 		res->err_status = swab32(res->err_status);
4552 		res->err_status1 = swab32(res->err_status1);
4553 		res->err_addr = swab32(res->err_addr);
4554 		bfa_trc(diag, res->addr);
4555 		bfa_trc(diag, res->exp);
4556 		bfa_trc(diag, res->act);
4557 		bfa_trc(diag, res->err_status);
4558 		bfa_trc(diag, res->err_status1);
4559 		bfa_trc(diag, res->err_addr);
4560 	}
4561 	diag->timer_active = 0;
4562 	diag->cbfn(diag->cbarg, diag->status);
4563 	diag->block = 0;
4564 }
4565 
4566 /*
4567  * Firmware ping
4568  */
4569 
4570 /*
4571  * Perform DMA test directly
4572  */
4573 static void
4574 diag_fwping_send(struct bfa_diag_s *diag)
4575 {
4576 	struct bfi_diag_fwping_req_s *fwping_req;
4577 	u32	i;
4578 
4579 	bfa_trc(diag, diag->fwping.dbuf_pa);
4580 
4581 	/* fill DMA area with pattern */
4582 	for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++)
4583 		*((u32 *)diag->fwping.dbuf_kva + i) = diag->fwping.data;
4584 
4585 	/* Fill mbox msg */
4586 	fwping_req = (struct bfi_diag_fwping_req_s *)diag->fwping.mbcmd.msg;
4587 
4588 	/* Setup SG list */
4589 	bfa_alen_set(&fwping_req->alen, BFI_DIAG_DMA_BUF_SZ,
4590 			diag->fwping.dbuf_pa);
4591 	/* Set up dma count */
4592 	fwping_req->count = cpu_to_be32(diag->fwping.count);
4593 	/* Set up data pattern */
4594 	fwping_req->data = diag->fwping.data;
4595 
4596 	/* build host command */
4597 	bfi_h2i_set(fwping_req->mh, BFI_MC_DIAG, BFI_DIAG_H2I_FWPING,
4598 		bfa_ioc_portid(diag->ioc));
4599 
4600 	/* send mbox cmd */
4601 	bfa_ioc_mbox_queue(diag->ioc, &diag->fwping.mbcmd);
4602 }
4603 
4604 static void
4605 diag_fwping_comp(struct bfa_diag_s *diag,
4606 		 struct bfi_diag_fwping_rsp_s *diag_rsp)
4607 {
4608 	u32	rsp_data = diag_rsp->data;
4609 	u8	rsp_dma_status = diag_rsp->dma_status;
4610 
4611 	bfa_trc(diag, rsp_data);
4612 	bfa_trc(diag, rsp_dma_status);
4613 
4614 	if (rsp_dma_status == BFA_STATUS_OK) {
4615 		u32	i, pat;
4616 		pat = (diag->fwping.count & 0x1) ? ~(diag->fwping.data) :
4617 			diag->fwping.data;
4618 		/* Check mbox data */
4619 		if (diag->fwping.data != rsp_data) {
4620 			bfa_trc(diag, rsp_data);
4621 			diag->fwping.result->dmastatus =
4622 					BFA_STATUS_DATACORRUPTED;
4623 			diag->fwping.status = BFA_STATUS_DATACORRUPTED;
4624 			diag->fwping.cbfn(diag->fwping.cbarg,
4625 					diag->fwping.status);
4626 			diag->fwping.lock = 0;
4627 			return;
4628 		}
4629 		/* Check dma pattern */
4630 		for (i = 0; i < (BFI_DIAG_DMA_BUF_SZ >> 2); i++) {
4631 			if (*((u32 *)diag->fwping.dbuf_kva + i) != pat) {
4632 				bfa_trc(diag, i);
4633 				bfa_trc(diag, pat);
4634 				bfa_trc(diag,
4635 					*((u32 *)diag->fwping.dbuf_kva + i));
4636 				diag->fwping.result->dmastatus =
4637 						BFA_STATUS_DATACORRUPTED;
4638 				diag->fwping.status = BFA_STATUS_DATACORRUPTED;
4639 				diag->fwping.cbfn(diag->fwping.cbarg,
4640 						diag->fwping.status);
4641 				diag->fwping.lock = 0;
4642 				return;
4643 			}
4644 		}
4645 		diag->fwping.result->dmastatus = BFA_STATUS_OK;
4646 		diag->fwping.status = BFA_STATUS_OK;
4647 		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
4648 		diag->fwping.lock = 0;
4649 	} else {
4650 		diag->fwping.status = BFA_STATUS_HDMA_FAILED;
4651 		diag->fwping.cbfn(diag->fwping.cbarg, diag->fwping.status);
4652 		diag->fwping.lock = 0;
4653 	}
4654 }
4655 
4656 /*
4657  * Temperature Sensor
4658  */
4659 
4660 static void
4661 diag_tempsensor_send(struct bfa_diag_s *diag)
4662 {
4663 	struct bfi_diag_ts_req_s *msg;
4664 
4665 	msg = (struct bfi_diag_ts_req_s *)diag->tsensor.mbcmd.msg;
4666 	bfa_trc(diag, msg->temp);
4667 	/* build host command */
4668 	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_TEMPSENSOR,
4669 		bfa_ioc_portid(diag->ioc));
4670 	/* send mbox cmd */
4671 	bfa_ioc_mbox_queue(diag->ioc, &diag->tsensor.mbcmd);
4672 }
4673 
4674 static void
4675 diag_tempsensor_comp(struct bfa_diag_s *diag, bfi_diag_ts_rsp_t *rsp)
4676 {
4677 	if (!diag->tsensor.lock) {
4678 		/* receiving response after ioc failure */
4679 		bfa_trc(diag, diag->tsensor.lock);
4680 		return;
4681 	}
4682 
4683 	/*
4684 	 * ASIC junction tempsensor is a reg read operation
4685 	 * it will always return OK
4686 	 */
4687 	diag->tsensor.temp->temp = be16_to_cpu(rsp->temp);
4688 	diag->tsensor.temp->ts_junc = rsp->ts_junc;
4689 	diag->tsensor.temp->ts_brd = rsp->ts_brd;
4690 
4691 	if (rsp->ts_brd) {
4692 		/* tsensor.temp->status is brd_temp status */
4693 		diag->tsensor.temp->status = rsp->status;
4694 		if (rsp->status == BFA_STATUS_OK) {
4695 			diag->tsensor.temp->brd_temp =
4696 				be16_to_cpu(rsp->brd_temp);
4697 		} else
4698 			diag->tsensor.temp->brd_temp = 0;
4699 	}
4700 
4701 	bfa_trc(diag, rsp->status);
4702 	bfa_trc(diag, rsp->ts_junc);
4703 	bfa_trc(diag, rsp->temp);
4704 	bfa_trc(diag, rsp->ts_brd);
4705 	bfa_trc(diag, rsp->brd_temp);
4706 
4707 	/* tsensor status is always good bcos we always have junction temp */
4708 	diag->tsensor.status = BFA_STATUS_OK;
4709 	diag->tsensor.cbfn(diag->tsensor.cbarg, diag->tsensor.status);
4710 	diag->tsensor.lock = 0;
4711 }
4712 
4713 /*
4714  *	LED Test command
4715  */
4716 static void
4717 diag_ledtest_send(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
4718 {
4719 	struct bfi_diag_ledtest_req_s  *msg;
4720 
4721 	msg = (struct bfi_diag_ledtest_req_s *)diag->ledtest.mbcmd.msg;
4722 	/* build host command */
4723 	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_LEDTEST,
4724 			bfa_ioc_portid(diag->ioc));
4725 
4726 	/*
4727 	 * convert the freq from N blinks per 10 sec to
4728 	 * crossbow ontime value. We do it here because division is need
4729 	 */
4730 	if (ledtest->freq)
4731 		ledtest->freq = 500 / ledtest->freq;
4732 
4733 	if (ledtest->freq == 0)
4734 		ledtest->freq = 1;
4735 
4736 	bfa_trc(diag, ledtest->freq);
4737 	/* mcpy(&ledtest_req->req, ledtest, sizeof(bfa_diag_ledtest_t)); */
4738 	msg->cmd = (u8) ledtest->cmd;
4739 	msg->color = (u8) ledtest->color;
4740 	msg->portid = bfa_ioc_portid(diag->ioc);
4741 	msg->led = ledtest->led;
4742 	msg->freq = cpu_to_be16(ledtest->freq);
4743 
4744 	/* send mbox cmd */
4745 	bfa_ioc_mbox_queue(diag->ioc, &diag->ledtest.mbcmd);
4746 }
4747 
4748 static void
4749 diag_ledtest_comp(struct bfa_diag_s *diag, struct bfi_diag_ledtest_rsp_s *msg)
4750 {
4751 	bfa_trc(diag, diag->ledtest.lock);
4752 	diag->ledtest.lock = BFA_FALSE;
4753 	/* no bfa_cb_queue is needed because driver is not waiting */
4754 }
4755 
4756 /*
4757  * Port beaconing
4758  */
4759 static void
4760 diag_portbeacon_send(struct bfa_diag_s *diag, bfa_boolean_t beacon, u32 sec)
4761 {
4762 	struct bfi_diag_portbeacon_req_s *msg;
4763 
4764 	msg = (struct bfi_diag_portbeacon_req_s *)diag->beacon.mbcmd.msg;
4765 	/* build host command */
4766 	bfi_h2i_set(msg->mh, BFI_MC_DIAG, BFI_DIAG_H2I_PORTBEACON,
4767 		bfa_ioc_portid(diag->ioc));
4768 	msg->beacon = beacon;
4769 	msg->period = cpu_to_be32(sec);
4770 	/* send mbox cmd */
4771 	bfa_ioc_mbox_queue(diag->ioc, &diag->beacon.mbcmd);
4772 }
4773 
4774 static void
4775 diag_portbeacon_comp(struct bfa_diag_s *diag)
4776 {
4777 	bfa_trc(diag, diag->beacon.state);
4778 	diag->beacon.state = BFA_FALSE;
4779 	if (diag->cbfn_beacon)
4780 		diag->cbfn_beacon(diag->dev, BFA_FALSE, diag->beacon.link_e2e);
4781 }
4782 
4783 /*
4784  *	Diag hmbox handler
4785  */
4786 void
4787 bfa_diag_intr(void *diagarg, struct bfi_mbmsg_s *msg)
4788 {
4789 	struct bfa_diag_s *diag = diagarg;
4790 
4791 	switch (msg->mh.msg_id) {
4792 	case BFI_DIAG_I2H_PORTBEACON:
4793 		diag_portbeacon_comp(diag);
4794 		break;
4795 	case BFI_DIAG_I2H_FWPING:
4796 		diag_fwping_comp(diag, (struct bfi_diag_fwping_rsp_s *) msg);
4797 		break;
4798 	case BFI_DIAG_I2H_TEMPSENSOR:
4799 		diag_tempsensor_comp(diag, (bfi_diag_ts_rsp_t *) msg);
4800 		break;
4801 	case BFI_DIAG_I2H_LEDTEST:
4802 		diag_ledtest_comp(diag, (struct bfi_diag_ledtest_rsp_s *) msg);
4803 		break;
4804 	default:
4805 		bfa_trc(diag, msg->mh.msg_id);
4806 		WARN_ON(1);
4807 	}
4808 }
4809 
4810 /*
4811  * Gen RAM Test
4812  *
4813  *   @param[in] *diag           - diag data struct
4814  *   @param[in] *memtest        - mem test params input from upper layer,
4815  *   @param[in] pattern         - mem test pattern
4816  *   @param[in] *result         - mem test result
4817  *   @param[in] cbfn            - mem test callback functioin
4818  *   @param[in] cbarg           - callback functioin arg
4819  *
4820  *   @param[out]
4821  */
4822 bfa_status_t
4823 bfa_diag_memtest(struct bfa_diag_s *diag, struct bfa_diag_memtest_s *memtest,
4824 		u32 pattern, struct bfa_diag_memtest_result *result,
4825 		bfa_cb_diag_t cbfn, void *cbarg)
4826 {
4827 	u32	memtest_tov;
4828 
4829 	bfa_trc(diag, pattern);
4830 
4831 	if (!bfa_ioc_adapter_is_disabled(diag->ioc))
4832 		return BFA_STATUS_ADAPTER_ENABLED;
4833 
4834 	/* check to see if there is another destructive diag cmd running */
4835 	if (diag->block) {
4836 		bfa_trc(diag, diag->block);
4837 		return BFA_STATUS_DEVBUSY;
4838 	} else
4839 		diag->block = 1;
4840 
4841 	diag->result = result;
4842 	diag->cbfn = cbfn;
4843 	diag->cbarg = cbarg;
4844 
4845 	/* download memtest code and take LPU0 out of reset */
4846 	bfa_ioc_boot(diag->ioc, BFI_FWBOOT_TYPE_MEMTEST, BFI_FWBOOT_ENV_OS);
4847 
4848 	memtest_tov = (bfa_ioc_asic_gen(diag->ioc) == BFI_ASIC_GEN_CT2) ?
4849 		       CT2_BFA_DIAG_MEMTEST_TOV : BFA_DIAG_MEMTEST_TOV;
4850 	bfa_timer_begin(diag->ioc->timer_mod, &diag->timer,
4851 			bfa_diag_memtest_done, diag, memtest_tov);
4852 	diag->timer_active = 1;
4853 	return BFA_STATUS_OK;
4854 }
4855 
4856 /*
4857  * DIAG firmware ping command
4858  *
4859  *   @param[in] *diag           - diag data struct
4860  *   @param[in] cnt             - dma loop count for testing PCIE
4861  *   @param[in] data            - data pattern to pass in fw
4862  *   @param[in] *result         - pt to bfa_diag_fwping_result_t data struct
4863  *   @param[in] cbfn            - callback function
4864  *   @param[in] *cbarg          - callback functioin arg
4865  *
4866  *   @param[out]
4867  */
4868 bfa_status_t
4869 bfa_diag_fwping(struct bfa_diag_s *diag, u32 cnt, u32 data,
4870 		struct bfa_diag_results_fwping *result, bfa_cb_diag_t cbfn,
4871 		void *cbarg)
4872 {
4873 	bfa_trc(diag, cnt);
4874 	bfa_trc(diag, data);
4875 
4876 	if (!bfa_ioc_is_operational(diag->ioc))
4877 		return BFA_STATUS_IOC_NON_OP;
4878 
4879 	if (bfa_asic_id_ct2(bfa_ioc_devid((diag->ioc))) &&
4880 	    ((diag->ioc)->clscode == BFI_PCIFN_CLASS_ETH))
4881 		return BFA_STATUS_CMD_NOTSUPP;
4882 
4883 	/* check to see if there is another destructive diag cmd running */
4884 	if (diag->block || diag->fwping.lock) {
4885 		bfa_trc(diag, diag->block);
4886 		bfa_trc(diag, diag->fwping.lock);
4887 		return BFA_STATUS_DEVBUSY;
4888 	}
4889 
4890 	/* Initialization */
4891 	diag->fwping.lock = 1;
4892 	diag->fwping.cbfn = cbfn;
4893 	diag->fwping.cbarg = cbarg;
4894 	diag->fwping.result = result;
4895 	diag->fwping.data = data;
4896 	diag->fwping.count = cnt;
4897 
4898 	/* Init test results */
4899 	diag->fwping.result->data = 0;
4900 	diag->fwping.result->status = BFA_STATUS_OK;
4901 
4902 	/* kick off the first ping */
4903 	diag_fwping_send(diag);
4904 	return BFA_STATUS_OK;
4905 }
4906 
4907 /*
4908  * Read Temperature Sensor
4909  *
4910  *   @param[in] *diag           - diag data struct
4911  *   @param[in] *result         - pt to bfa_diag_temp_t data struct
4912  *   @param[in] cbfn            - callback function
4913  *   @param[in] *cbarg          - callback functioin arg
4914  *
4915  *   @param[out]
4916  */
4917 bfa_status_t
4918 bfa_diag_tsensor_query(struct bfa_diag_s *diag,
4919 		struct bfa_diag_results_tempsensor_s *result,
4920 		bfa_cb_diag_t cbfn, void *cbarg)
4921 {
4922 	/* check to see if there is a destructive diag cmd running */
4923 	if (diag->block || diag->tsensor.lock) {
4924 		bfa_trc(diag, diag->block);
4925 		bfa_trc(diag, diag->tsensor.lock);
4926 		return BFA_STATUS_DEVBUSY;
4927 	}
4928 
4929 	if (!bfa_ioc_is_operational(diag->ioc))
4930 		return BFA_STATUS_IOC_NON_OP;
4931 
4932 	/* Init diag mod params */
4933 	diag->tsensor.lock = 1;
4934 	diag->tsensor.temp = result;
4935 	diag->tsensor.cbfn = cbfn;
4936 	diag->tsensor.cbarg = cbarg;
4937 	diag->tsensor.status = BFA_STATUS_OK;
4938 
4939 	/* Send msg to fw */
4940 	diag_tempsensor_send(diag);
4941 
4942 	return BFA_STATUS_OK;
4943 }
4944 
4945 /*
4946  * LED Test command
4947  *
4948  *   @param[in] *diag           - diag data struct
4949  *   @param[in] *ledtest        - pt to ledtest data structure
4950  *
4951  *   @param[out]
4952  */
4953 bfa_status_t
4954 bfa_diag_ledtest(struct bfa_diag_s *diag, struct bfa_diag_ledtest_s *ledtest)
4955 {
4956 	bfa_trc(diag, ledtest->cmd);
4957 
4958 	if (!bfa_ioc_is_operational(diag->ioc))
4959 		return BFA_STATUS_IOC_NON_OP;
4960 
4961 	if (diag->beacon.state)
4962 		return BFA_STATUS_BEACON_ON;
4963 
4964 	if (diag->ledtest.lock)
4965 		return BFA_STATUS_LEDTEST_OP;
4966 
4967 	/* Send msg to fw */
4968 	diag->ledtest.lock = BFA_TRUE;
4969 	diag_ledtest_send(diag, ledtest);
4970 
4971 	return BFA_STATUS_OK;
4972 }
4973 
4974 /*
4975  * Port beaconing command
4976  *
4977  *   @param[in] *diag           - diag data struct
4978  *   @param[in] beacon          - port beaconing 1:ON   0:OFF
4979  *   @param[in] link_e2e_beacon - link beaconing 1:ON   0:OFF
4980  *   @param[in] sec             - beaconing duration in seconds
4981  *
4982  *   @param[out]
4983  */
4984 bfa_status_t
4985 bfa_diag_beacon_port(struct bfa_diag_s *diag, bfa_boolean_t beacon,
4986 		bfa_boolean_t link_e2e_beacon, uint32_t sec)
4987 {
4988 	bfa_trc(diag, beacon);
4989 	bfa_trc(diag, link_e2e_beacon);
4990 	bfa_trc(diag, sec);
4991 
4992 	if (!bfa_ioc_is_operational(diag->ioc))
4993 		return BFA_STATUS_IOC_NON_OP;
4994 
4995 	if (diag->ledtest.lock)
4996 		return BFA_STATUS_LEDTEST_OP;
4997 
4998 	if (diag->beacon.state && beacon)       /* beacon alread on */
4999 		return BFA_STATUS_BEACON_ON;
5000 
5001 	diag->beacon.state	= beacon;
5002 	diag->beacon.link_e2e	= link_e2e_beacon;
5003 	if (diag->cbfn_beacon)
5004 		diag->cbfn_beacon(diag->dev, beacon, link_e2e_beacon);
5005 
5006 	/* Send msg to fw */
5007 	diag_portbeacon_send(diag, beacon, sec);
5008 
5009 	return BFA_STATUS_OK;
5010 }
5011 
5012 /*
5013  * Return DMA memory needed by diag module.
5014  */
5015 u32
5016 bfa_diag_meminfo(void)
5017 {
5018 	return BFA_ROUNDUP(BFI_DIAG_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5019 }
5020 
5021 /*
5022  *	Attach virtual and physical memory for Diag.
5023  */
5024 void
5025 bfa_diag_attach(struct bfa_diag_s *diag, struct bfa_ioc_s *ioc, void *dev,
5026 	bfa_cb_diag_beacon_t cbfn_beacon, struct bfa_trc_mod_s *trcmod)
5027 {
5028 	diag->dev = dev;
5029 	diag->ioc = ioc;
5030 	diag->trcmod = trcmod;
5031 
5032 	diag->block = 0;
5033 	diag->cbfn = NULL;
5034 	diag->cbarg = NULL;
5035 	diag->result = NULL;
5036 	diag->cbfn_beacon = cbfn_beacon;
5037 
5038 	bfa_ioc_mbox_regisr(diag->ioc, BFI_MC_DIAG, bfa_diag_intr, diag);
5039 	bfa_q_qe_init(&diag->ioc_notify);
5040 	bfa_ioc_notify_init(&diag->ioc_notify, bfa_diag_notify, diag);
5041 	list_add_tail(&diag->ioc_notify.qe, &diag->ioc->notify_q);
5042 }
5043 
5044 void
5045 bfa_diag_memclaim(struct bfa_diag_s *diag, u8 *dm_kva, u64 dm_pa)
5046 {
5047 	diag->fwping.dbuf_kva = dm_kva;
5048 	diag->fwping.dbuf_pa = dm_pa;
5049 	memset(diag->fwping.dbuf_kva, 0, BFI_DIAG_DMA_BUF_SZ);
5050 }
5051 
5052 /*
5053  *	PHY module specific
5054  */
5055 #define BFA_PHY_DMA_BUF_SZ	0x02000         /* 8k dma buffer */
5056 #define BFA_PHY_LOCK_STATUS	0x018878        /* phy semaphore status reg */
5057 
5058 static void
5059 bfa_phy_ntoh32(u32 *obuf, u32 *ibuf, int sz)
5060 {
5061 	int i, m = sz >> 2;
5062 
5063 	for (i = 0; i < m; i++)
5064 		obuf[i] = be32_to_cpu(ibuf[i]);
5065 }
5066 
5067 static bfa_boolean_t
5068 bfa_phy_present(struct bfa_phy_s *phy)
5069 {
5070 	return (phy->ioc->attr->card_type == BFA_MFG_TYPE_LIGHTNING);
5071 }
5072 
5073 static void
5074 bfa_phy_notify(void *cbarg, enum bfa_ioc_event_e event)
5075 {
5076 	struct bfa_phy_s *phy = cbarg;
5077 
5078 	bfa_trc(phy, event);
5079 
5080 	switch (event) {
5081 	case BFA_IOC_E_DISABLED:
5082 	case BFA_IOC_E_FAILED:
5083 		if (phy->op_busy) {
5084 			phy->status = BFA_STATUS_IOC_FAILURE;
5085 			phy->cbfn(phy->cbarg, phy->status);
5086 			phy->op_busy = 0;
5087 		}
5088 		break;
5089 
5090 	default:
5091 		break;
5092 	}
5093 }
5094 
5095 /*
5096  * Send phy attribute query request.
5097  *
5098  * @param[in] cbarg - callback argument
5099  */
5100 static void
5101 bfa_phy_query_send(void *cbarg)
5102 {
5103 	struct bfa_phy_s *phy = cbarg;
5104 	struct bfi_phy_query_req_s *msg =
5105 			(struct bfi_phy_query_req_s *) phy->mb.msg;
5106 
5107 	msg->instance = phy->instance;
5108 	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_QUERY_REQ,
5109 		bfa_ioc_portid(phy->ioc));
5110 	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_attr_s), phy->dbuf_pa);
5111 	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5112 }
5113 
5114 /*
5115  * Send phy write request.
5116  *
5117  * @param[in] cbarg - callback argument
5118  */
5119 static void
5120 bfa_phy_write_send(void *cbarg)
5121 {
5122 	struct bfa_phy_s *phy = cbarg;
5123 	struct bfi_phy_write_req_s *msg =
5124 			(struct bfi_phy_write_req_s *) phy->mb.msg;
5125 	u32	len;
5126 	u16	*buf, *dbuf;
5127 	int	i, sz;
5128 
5129 	msg->instance = phy->instance;
5130 	msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
5131 	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
5132 			phy->residue : BFA_PHY_DMA_BUF_SZ;
5133 	msg->length = cpu_to_be32(len);
5134 
5135 	/* indicate if it's the last msg of the whole write operation */
5136 	msg->last = (len == phy->residue) ? 1 : 0;
5137 
5138 	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_WRITE_REQ,
5139 		bfa_ioc_portid(phy->ioc));
5140 	bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
5141 
5142 	buf = (u16 *) (phy->ubuf + phy->offset);
5143 	dbuf = (u16 *)phy->dbuf_kva;
5144 	sz = len >> 1;
5145 	for (i = 0; i < sz; i++)
5146 		buf[i] = cpu_to_be16(dbuf[i]);
5147 
5148 	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5149 
5150 	phy->residue -= len;
5151 	phy->offset += len;
5152 }
5153 
5154 /*
5155  * Send phy read request.
5156  *
5157  * @param[in] cbarg - callback argument
5158  */
5159 static void
5160 bfa_phy_read_send(void *cbarg)
5161 {
5162 	struct bfa_phy_s *phy = cbarg;
5163 	struct bfi_phy_read_req_s *msg =
5164 			(struct bfi_phy_read_req_s *) phy->mb.msg;
5165 	u32	len;
5166 
5167 	msg->instance = phy->instance;
5168 	msg->offset = cpu_to_be32(phy->addr_off + phy->offset);
5169 	len = (phy->residue < BFA_PHY_DMA_BUF_SZ) ?
5170 			phy->residue : BFA_PHY_DMA_BUF_SZ;
5171 	msg->length = cpu_to_be32(len);
5172 	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_READ_REQ,
5173 		bfa_ioc_portid(phy->ioc));
5174 	bfa_alen_set(&msg->alen, len, phy->dbuf_pa);
5175 	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5176 }
5177 
5178 /*
5179  * Send phy stats request.
5180  *
5181  * @param[in] cbarg - callback argument
5182  */
5183 static void
5184 bfa_phy_stats_send(void *cbarg)
5185 {
5186 	struct bfa_phy_s *phy = cbarg;
5187 	struct bfi_phy_stats_req_s *msg =
5188 			(struct bfi_phy_stats_req_s *) phy->mb.msg;
5189 
5190 	msg->instance = phy->instance;
5191 	bfi_h2i_set(msg->mh, BFI_MC_PHY, BFI_PHY_H2I_STATS_REQ,
5192 		bfa_ioc_portid(phy->ioc));
5193 	bfa_alen_set(&msg->alen, sizeof(struct bfa_phy_stats_s), phy->dbuf_pa);
5194 	bfa_ioc_mbox_queue(phy->ioc, &phy->mb);
5195 }
5196 
5197 /*
5198  * Flash memory info API.
5199  *
5200  * @param[in] mincfg - minimal cfg variable
5201  */
5202 u32
5203 bfa_phy_meminfo(bfa_boolean_t mincfg)
5204 {
5205 	/* min driver doesn't need phy */
5206 	if (mincfg)
5207 		return 0;
5208 
5209 	return BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5210 }
5211 
5212 /*
5213  * Flash attach API.
5214  *
5215  * @param[in] phy - phy structure
5216  * @param[in] ioc  - ioc structure
5217  * @param[in] dev  - device structure
5218  * @param[in] trcmod - trace module
5219  * @param[in] logmod - log module
5220  */
5221 void
5222 bfa_phy_attach(struct bfa_phy_s *phy, struct bfa_ioc_s *ioc, void *dev,
5223 		struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
5224 {
5225 	phy->ioc = ioc;
5226 	phy->trcmod = trcmod;
5227 	phy->cbfn = NULL;
5228 	phy->cbarg = NULL;
5229 	phy->op_busy = 0;
5230 
5231 	bfa_ioc_mbox_regisr(phy->ioc, BFI_MC_PHY, bfa_phy_intr, phy);
5232 	bfa_q_qe_init(&phy->ioc_notify);
5233 	bfa_ioc_notify_init(&phy->ioc_notify, bfa_phy_notify, phy);
5234 	list_add_tail(&phy->ioc_notify.qe, &phy->ioc->notify_q);
5235 
5236 	/* min driver doesn't need phy */
5237 	if (mincfg) {
5238 		phy->dbuf_kva = NULL;
5239 		phy->dbuf_pa = 0;
5240 	}
5241 }
5242 
5243 /*
5244  * Claim memory for phy
5245  *
5246  * @param[in] phy - phy structure
5247  * @param[in] dm_kva - pointer to virtual memory address
5248  * @param[in] dm_pa - physical memory address
5249  * @param[in] mincfg - minimal cfg variable
5250  */
5251 void
5252 bfa_phy_memclaim(struct bfa_phy_s *phy, u8 *dm_kva, u64 dm_pa,
5253 		bfa_boolean_t mincfg)
5254 {
5255 	if (mincfg)
5256 		return;
5257 
5258 	phy->dbuf_kva = dm_kva;
5259 	phy->dbuf_pa = dm_pa;
5260 	memset(phy->dbuf_kva, 0, BFA_PHY_DMA_BUF_SZ);
5261 	dm_kva += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5262 	dm_pa += BFA_ROUNDUP(BFA_PHY_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
5263 }
5264 
5265 bfa_boolean_t
5266 bfa_phy_busy(struct bfa_ioc_s *ioc)
5267 {
5268 	void __iomem	*rb;
5269 
5270 	rb = bfa_ioc_bar0(ioc);
5271 	return readl(rb + BFA_PHY_LOCK_STATUS);
5272 }
5273 
5274 /*
5275  * Get phy attribute.
5276  *
5277  * @param[in] phy - phy structure
5278  * @param[in] attr - phy attribute structure
5279  * @param[in] cbfn - callback function
5280  * @param[in] cbarg - callback argument
5281  *
5282  * Return status.
5283  */
5284 bfa_status_t
5285 bfa_phy_get_attr(struct bfa_phy_s *phy, u8 instance,
5286 		struct bfa_phy_attr_s *attr, bfa_cb_phy_t cbfn, void *cbarg)
5287 {
5288 	bfa_trc(phy, BFI_PHY_H2I_QUERY_REQ);
5289 	bfa_trc(phy, instance);
5290 
5291 	if (!bfa_phy_present(phy))
5292 		return BFA_STATUS_PHY_NOT_PRESENT;
5293 
5294 	if (!bfa_ioc_is_operational(phy->ioc))
5295 		return BFA_STATUS_IOC_NON_OP;
5296 
5297 	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5298 		bfa_trc(phy, phy->op_busy);
5299 		return BFA_STATUS_DEVBUSY;
5300 	}
5301 
5302 	phy->op_busy = 1;
5303 	phy->cbfn = cbfn;
5304 	phy->cbarg = cbarg;
5305 	phy->instance = instance;
5306 	phy->ubuf = (uint8_t *) attr;
5307 	bfa_phy_query_send(phy);
5308 
5309 	return BFA_STATUS_OK;
5310 }
5311 
5312 /*
5313  * Get phy stats.
5314  *
5315  * @param[in] phy - phy structure
5316  * @param[in] instance - phy image instance
5317  * @param[in] stats - pointer to phy stats
5318  * @param[in] cbfn - callback function
5319  * @param[in] cbarg - callback argument
5320  *
5321  * Return status.
5322  */
5323 bfa_status_t
5324 bfa_phy_get_stats(struct bfa_phy_s *phy, u8 instance,
5325 		struct bfa_phy_stats_s *stats,
5326 		bfa_cb_phy_t cbfn, void *cbarg)
5327 {
5328 	bfa_trc(phy, BFI_PHY_H2I_STATS_REQ);
5329 	bfa_trc(phy, instance);
5330 
5331 	if (!bfa_phy_present(phy))
5332 		return BFA_STATUS_PHY_NOT_PRESENT;
5333 
5334 	if (!bfa_ioc_is_operational(phy->ioc))
5335 		return BFA_STATUS_IOC_NON_OP;
5336 
5337 	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5338 		bfa_trc(phy, phy->op_busy);
5339 		return BFA_STATUS_DEVBUSY;
5340 	}
5341 
5342 	phy->op_busy = 1;
5343 	phy->cbfn = cbfn;
5344 	phy->cbarg = cbarg;
5345 	phy->instance = instance;
5346 	phy->ubuf = (u8 *) stats;
5347 	bfa_phy_stats_send(phy);
5348 
5349 	return BFA_STATUS_OK;
5350 }
5351 
5352 /*
5353  * Update phy image.
5354  *
5355  * @param[in] phy - phy structure
5356  * @param[in] instance - phy image instance
5357  * @param[in] buf - update data buffer
5358  * @param[in] len - data buffer length
5359  * @param[in] offset - offset relative to starting address
5360  * @param[in] cbfn - callback function
5361  * @param[in] cbarg - callback argument
5362  *
5363  * Return status.
5364  */
5365 bfa_status_t
5366 bfa_phy_update(struct bfa_phy_s *phy, u8 instance,
5367 		void *buf, u32 len, u32 offset,
5368 		bfa_cb_phy_t cbfn, void *cbarg)
5369 {
5370 	bfa_trc(phy, BFI_PHY_H2I_WRITE_REQ);
5371 	bfa_trc(phy, instance);
5372 	bfa_trc(phy, len);
5373 	bfa_trc(phy, offset);
5374 
5375 	if (!bfa_phy_present(phy))
5376 		return BFA_STATUS_PHY_NOT_PRESENT;
5377 
5378 	if (!bfa_ioc_is_operational(phy->ioc))
5379 		return BFA_STATUS_IOC_NON_OP;
5380 
5381 	/* 'len' must be in word (4-byte) boundary */
5382 	if (!len || (len & 0x03))
5383 		return BFA_STATUS_FAILED;
5384 
5385 	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5386 		bfa_trc(phy, phy->op_busy);
5387 		return BFA_STATUS_DEVBUSY;
5388 	}
5389 
5390 	phy->op_busy = 1;
5391 	phy->cbfn = cbfn;
5392 	phy->cbarg = cbarg;
5393 	phy->instance = instance;
5394 	phy->residue = len;
5395 	phy->offset = 0;
5396 	phy->addr_off = offset;
5397 	phy->ubuf = buf;
5398 
5399 	bfa_phy_write_send(phy);
5400 	return BFA_STATUS_OK;
5401 }
5402 
5403 /*
5404  * Read phy image.
5405  *
5406  * @param[in] phy - phy structure
5407  * @param[in] instance - phy image instance
5408  * @param[in] buf - read data buffer
5409  * @param[in] len - data buffer length
5410  * @param[in] offset - offset relative to starting address
5411  * @param[in] cbfn - callback function
5412  * @param[in] cbarg - callback argument
5413  *
5414  * Return status.
5415  */
5416 bfa_status_t
5417 bfa_phy_read(struct bfa_phy_s *phy, u8 instance,
5418 		void *buf, u32 len, u32 offset,
5419 		bfa_cb_phy_t cbfn, void *cbarg)
5420 {
5421 	bfa_trc(phy, BFI_PHY_H2I_READ_REQ);
5422 	bfa_trc(phy, instance);
5423 	bfa_trc(phy, len);
5424 	bfa_trc(phy, offset);
5425 
5426 	if (!bfa_phy_present(phy))
5427 		return BFA_STATUS_PHY_NOT_PRESENT;
5428 
5429 	if (!bfa_ioc_is_operational(phy->ioc))
5430 		return BFA_STATUS_IOC_NON_OP;
5431 
5432 	/* 'len' must be in word (4-byte) boundary */
5433 	if (!len || (len & 0x03))
5434 		return BFA_STATUS_FAILED;
5435 
5436 	if (phy->op_busy || bfa_phy_busy(phy->ioc)) {
5437 		bfa_trc(phy, phy->op_busy);
5438 		return BFA_STATUS_DEVBUSY;
5439 	}
5440 
5441 	phy->op_busy = 1;
5442 	phy->cbfn = cbfn;
5443 	phy->cbarg = cbarg;
5444 	phy->instance = instance;
5445 	phy->residue = len;
5446 	phy->offset = 0;
5447 	phy->addr_off = offset;
5448 	phy->ubuf = buf;
5449 	bfa_phy_read_send(phy);
5450 
5451 	return BFA_STATUS_OK;
5452 }
5453 
5454 /*
5455  * Process phy response messages upon receiving interrupts.
5456  *
5457  * @param[in] phyarg - phy structure
5458  * @param[in] msg - message structure
5459  */
5460 void
5461 bfa_phy_intr(void *phyarg, struct bfi_mbmsg_s *msg)
5462 {
5463 	struct bfa_phy_s *phy = phyarg;
5464 	u32	status;
5465 
5466 	union {
5467 		struct bfi_phy_query_rsp_s *query;
5468 		struct bfi_phy_stats_rsp_s *stats;
5469 		struct bfi_phy_write_rsp_s *write;
5470 		struct bfi_phy_read_rsp_s *read;
5471 		struct bfi_mbmsg_s   *msg;
5472 	} m;
5473 
5474 	m.msg = msg;
5475 	bfa_trc(phy, msg->mh.msg_id);
5476 
5477 	if (!phy->op_busy) {
5478 		/* receiving response after ioc failure */
5479 		bfa_trc(phy, 0x9999);
5480 		return;
5481 	}
5482 
5483 	switch (msg->mh.msg_id) {
5484 	case BFI_PHY_I2H_QUERY_RSP:
5485 		status = be32_to_cpu(m.query->status);
5486 		bfa_trc(phy, status);
5487 
5488 		if (status == BFA_STATUS_OK) {
5489 			struct bfa_phy_attr_s *attr =
5490 				(struct bfa_phy_attr_s *) phy->ubuf;
5491 			bfa_phy_ntoh32((u32 *)attr, (u32 *)phy->dbuf_kva,
5492 					sizeof(struct bfa_phy_attr_s));
5493 			bfa_trc(phy, attr->status);
5494 			bfa_trc(phy, attr->length);
5495 		}
5496 
5497 		phy->status = status;
5498 		phy->op_busy = 0;
5499 		if (phy->cbfn)
5500 			phy->cbfn(phy->cbarg, phy->status);
5501 		break;
5502 	case BFI_PHY_I2H_STATS_RSP:
5503 		status = be32_to_cpu(m.stats->status);
5504 		bfa_trc(phy, status);
5505 
5506 		if (status == BFA_STATUS_OK) {
5507 			struct bfa_phy_stats_s *stats =
5508 				(struct bfa_phy_stats_s *) phy->ubuf;
5509 			bfa_phy_ntoh32((u32 *)stats, (u32 *)phy->dbuf_kva,
5510 				sizeof(struct bfa_phy_stats_s));
5511 				bfa_trc(phy, stats->status);
5512 		}
5513 
5514 		phy->status = status;
5515 		phy->op_busy = 0;
5516 		if (phy->cbfn)
5517 			phy->cbfn(phy->cbarg, phy->status);
5518 		break;
5519 	case BFI_PHY_I2H_WRITE_RSP:
5520 		status = be32_to_cpu(m.write->status);
5521 		bfa_trc(phy, status);
5522 
5523 		if (status != BFA_STATUS_OK || phy->residue == 0) {
5524 			phy->status = status;
5525 			phy->op_busy = 0;
5526 			if (phy->cbfn)
5527 				phy->cbfn(phy->cbarg, phy->status);
5528 		} else {
5529 			bfa_trc(phy, phy->offset);
5530 			bfa_phy_write_send(phy);
5531 		}
5532 		break;
5533 	case BFI_PHY_I2H_READ_RSP:
5534 		status = be32_to_cpu(m.read->status);
5535 		bfa_trc(phy, status);
5536 
5537 		if (status != BFA_STATUS_OK) {
5538 			phy->status = status;
5539 			phy->op_busy = 0;
5540 			if (phy->cbfn)
5541 				phy->cbfn(phy->cbarg, phy->status);
5542 		} else {
5543 			u32 len = be32_to_cpu(m.read->length);
5544 			u16 *buf = (u16 *)(phy->ubuf + phy->offset);
5545 			u16 *dbuf = (u16 *)phy->dbuf_kva;
5546 			int i, sz = len >> 1;
5547 
5548 			bfa_trc(phy, phy->offset);
5549 			bfa_trc(phy, len);
5550 
5551 			for (i = 0; i < sz; i++)
5552 				buf[i] = be16_to_cpu(dbuf[i]);
5553 
5554 			phy->residue -= len;
5555 			phy->offset += len;
5556 
5557 			if (phy->residue == 0) {
5558 				phy->status = status;
5559 				phy->op_busy = 0;
5560 				if (phy->cbfn)
5561 					phy->cbfn(phy->cbarg, phy->status);
5562 			} else
5563 				bfa_phy_read_send(phy);
5564 		}
5565 		break;
5566 	default:
5567 		WARN_ON(1);
5568 	}
5569 }
5570 
5571 /*
5572  *	DCONF module specific
5573  */
5574 
5575 BFA_MODULE(dconf);
5576 
5577 /*
5578  * DCONF state machine events
5579  */
5580 enum bfa_dconf_event {
5581 	BFA_DCONF_SM_INIT		= 1,	/* dconf Init */
5582 	BFA_DCONF_SM_FLASH_COMP		= 2,	/* read/write to flash */
5583 	BFA_DCONF_SM_WR			= 3,	/* binding change, map */
5584 	BFA_DCONF_SM_TIMEOUT		= 4,	/* Start timer */
5585 	BFA_DCONF_SM_EXIT		= 5,	/* exit dconf module */
5586 	BFA_DCONF_SM_IOCDISABLE		= 6,	/* IOC disable event */
5587 };
5588 
5589 /* forward declaration of DCONF state machine */
5590 static void bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf,
5591 				enum bfa_dconf_event event);
5592 static void bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
5593 				enum bfa_dconf_event event);
5594 static void bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf,
5595 				enum bfa_dconf_event event);
5596 static void bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf,
5597 				enum bfa_dconf_event event);
5598 static void bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf,
5599 				enum bfa_dconf_event event);
5600 static void bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,
5601 				enum bfa_dconf_event event);
5602 static void bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
5603 				enum bfa_dconf_event event);
5604 
5605 static void bfa_dconf_cbfn(void *dconf, bfa_status_t status);
5606 static void bfa_dconf_timer(void *cbarg);
5607 static bfa_status_t bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf);
5608 static void bfa_dconf_init_cb(void *arg, bfa_status_t status);
5609 
5610 /*
5611  * Beginning state of dconf module. Waiting for an event to start.
5612  */
5613 static void
5614 bfa_dconf_sm_uninit(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5615 {
5616 	bfa_status_t bfa_status;
5617 	bfa_trc(dconf->bfa, event);
5618 
5619 	switch (event) {
5620 	case BFA_DCONF_SM_INIT:
5621 		if (dconf->min_cfg) {
5622 			bfa_trc(dconf->bfa, dconf->min_cfg);
5623 			bfa_fsm_send_event(&dconf->bfa->iocfc,
5624 					IOCFC_E_DCONF_DONE);
5625 			return;
5626 		}
5627 		bfa_sm_set_state(dconf, bfa_dconf_sm_flash_read);
5628 		bfa_timer_start(dconf->bfa, &dconf->timer,
5629 			bfa_dconf_timer, dconf, 2 * BFA_DCONF_UPDATE_TOV);
5630 		bfa_status = bfa_flash_read_part(BFA_FLASH(dconf->bfa),
5631 					BFA_FLASH_PART_DRV, dconf->instance,
5632 					dconf->dconf,
5633 					sizeof(struct bfa_dconf_s), 0,
5634 					bfa_dconf_init_cb, dconf->bfa);
5635 		if (bfa_status != BFA_STATUS_OK) {
5636 			bfa_timer_stop(&dconf->timer);
5637 			bfa_dconf_init_cb(dconf->bfa, BFA_STATUS_FAILED);
5638 			bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5639 			return;
5640 		}
5641 		break;
5642 	case BFA_DCONF_SM_EXIT:
5643 		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5644 	case BFA_DCONF_SM_IOCDISABLE:
5645 	case BFA_DCONF_SM_WR:
5646 	case BFA_DCONF_SM_FLASH_COMP:
5647 		break;
5648 	default:
5649 		bfa_sm_fault(dconf->bfa, event);
5650 	}
5651 }
5652 
5653 /*
5654  * Read flash for dconf entries and make a call back to the driver once done.
5655  */
5656 static void
5657 bfa_dconf_sm_flash_read(struct bfa_dconf_mod_s *dconf,
5658 			enum bfa_dconf_event event)
5659 {
5660 	bfa_trc(dconf->bfa, event);
5661 
5662 	switch (event) {
5663 	case BFA_DCONF_SM_FLASH_COMP:
5664 		bfa_timer_stop(&dconf->timer);
5665 		bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5666 		break;
5667 	case BFA_DCONF_SM_TIMEOUT:
5668 		bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5669 		bfa_ioc_suspend(&dconf->bfa->ioc);
5670 		break;
5671 	case BFA_DCONF_SM_EXIT:
5672 		bfa_timer_stop(&dconf->timer);
5673 		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5674 		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5675 		break;
5676 	case BFA_DCONF_SM_IOCDISABLE:
5677 		bfa_timer_stop(&dconf->timer);
5678 		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5679 		break;
5680 	default:
5681 		bfa_sm_fault(dconf->bfa, event);
5682 	}
5683 }
5684 
5685 /*
5686  * DCONF Module is in ready state. Has completed the initialization.
5687  */
5688 static void
5689 bfa_dconf_sm_ready(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5690 {
5691 	bfa_trc(dconf->bfa, event);
5692 
5693 	switch (event) {
5694 	case BFA_DCONF_SM_WR:
5695 		bfa_timer_start(dconf->bfa, &dconf->timer,
5696 			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5697 		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
5698 		break;
5699 	case BFA_DCONF_SM_EXIT:
5700 		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5701 		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5702 		break;
5703 	case BFA_DCONF_SM_INIT:
5704 	case BFA_DCONF_SM_IOCDISABLE:
5705 		break;
5706 	default:
5707 		bfa_sm_fault(dconf->bfa, event);
5708 	}
5709 }
5710 
5711 /*
5712  * entries are dirty, write back to the flash.
5713  */
5714 
5715 static void
5716 bfa_dconf_sm_dirty(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5717 {
5718 	bfa_trc(dconf->bfa, event);
5719 
5720 	switch (event) {
5721 	case BFA_DCONF_SM_TIMEOUT:
5722 		bfa_sm_set_state(dconf, bfa_dconf_sm_sync);
5723 		bfa_dconf_flash_write(dconf);
5724 		break;
5725 	case BFA_DCONF_SM_WR:
5726 		bfa_timer_stop(&dconf->timer);
5727 		bfa_timer_start(dconf->bfa, &dconf->timer,
5728 			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5729 		break;
5730 	case BFA_DCONF_SM_EXIT:
5731 		bfa_timer_stop(&dconf->timer);
5732 		bfa_timer_start(dconf->bfa, &dconf->timer,
5733 			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5734 		bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);
5735 		bfa_dconf_flash_write(dconf);
5736 		break;
5737 	case BFA_DCONF_SM_FLASH_COMP:
5738 		break;
5739 	case BFA_DCONF_SM_IOCDISABLE:
5740 		bfa_timer_stop(&dconf->timer);
5741 		bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);
5742 		break;
5743 	default:
5744 		bfa_sm_fault(dconf->bfa, event);
5745 	}
5746 }
5747 
5748 /*
5749  * Sync the dconf entries to the flash.
5750  */
5751 static void
5752 bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf,
5753 			enum bfa_dconf_event event)
5754 {
5755 	bfa_trc(dconf->bfa, event);
5756 
5757 	switch (event) {
5758 	case BFA_DCONF_SM_IOCDISABLE:
5759 	case BFA_DCONF_SM_FLASH_COMP:
5760 		bfa_timer_stop(&dconf->timer);
5761 	case BFA_DCONF_SM_TIMEOUT:
5762 		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5763 		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5764 		break;
5765 	default:
5766 		bfa_sm_fault(dconf->bfa, event);
5767 	}
5768 }
5769 
5770 static void
5771 bfa_dconf_sm_sync(struct bfa_dconf_mod_s *dconf, enum bfa_dconf_event event)
5772 {
5773 	bfa_trc(dconf->bfa, event);
5774 
5775 	switch (event) {
5776 	case BFA_DCONF_SM_FLASH_COMP:
5777 		bfa_sm_set_state(dconf, bfa_dconf_sm_ready);
5778 		break;
5779 	case BFA_DCONF_SM_WR:
5780 		bfa_timer_start(dconf->bfa, &dconf->timer,
5781 			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5782 		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
5783 		break;
5784 	case BFA_DCONF_SM_EXIT:
5785 		bfa_timer_start(dconf->bfa, &dconf->timer,
5786 			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5787 		bfa_sm_set_state(dconf, bfa_dconf_sm_final_sync);
5788 		break;
5789 	case BFA_DCONF_SM_IOCDISABLE:
5790 		bfa_sm_set_state(dconf, bfa_dconf_sm_iocdown_dirty);
5791 		break;
5792 	default:
5793 		bfa_sm_fault(dconf->bfa, event);
5794 	}
5795 }
5796 
5797 static void
5798 bfa_dconf_sm_iocdown_dirty(struct bfa_dconf_mod_s *dconf,
5799 			enum bfa_dconf_event event)
5800 {
5801 	bfa_trc(dconf->bfa, event);
5802 
5803 	switch (event) {
5804 	case BFA_DCONF_SM_INIT:
5805 		bfa_timer_start(dconf->bfa, &dconf->timer,
5806 			bfa_dconf_timer, dconf, BFA_DCONF_UPDATE_TOV);
5807 		bfa_sm_set_state(dconf, bfa_dconf_sm_dirty);
5808 		break;
5809 	case BFA_DCONF_SM_EXIT:
5810 		bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5811 		bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE);
5812 		break;
5813 	case BFA_DCONF_SM_IOCDISABLE:
5814 		break;
5815 	default:
5816 		bfa_sm_fault(dconf->bfa, event);
5817 	}
5818 }
5819 
5820 /*
5821  * Compute and return memory needed by DRV_CFG module.
5822  */
5823 static void
5824 bfa_dconf_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo,
5825 		  struct bfa_s *bfa)
5826 {
5827 	struct bfa_mem_kva_s *dconf_kva = BFA_MEM_DCONF_KVA(bfa);
5828 
5829 	if (cfg->drvcfg.min_cfg)
5830 		bfa_mem_kva_setup(meminfo, dconf_kva,
5831 				sizeof(struct bfa_dconf_hdr_s));
5832 	else
5833 		bfa_mem_kva_setup(meminfo, dconf_kva,
5834 				sizeof(struct bfa_dconf_s));
5835 }
5836 
5837 static void
5838 bfa_dconf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg,
5839 		struct bfa_pcidev_s *pcidev)
5840 {
5841 	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5842 
5843 	dconf->bfad = bfad;
5844 	dconf->bfa = bfa;
5845 	dconf->instance = bfa->ioc.port_id;
5846 	bfa_trc(bfa, dconf->instance);
5847 
5848 	dconf->dconf = (struct bfa_dconf_s *) bfa_mem_kva_curp(dconf);
5849 	if (cfg->drvcfg.min_cfg) {
5850 		bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_hdr_s);
5851 		dconf->min_cfg = BFA_TRUE;
5852 	} else {
5853 		dconf->min_cfg = BFA_FALSE;
5854 		bfa_mem_kva_curp(dconf) += sizeof(struct bfa_dconf_s);
5855 	}
5856 
5857 	bfa_dconf_read_data_valid(bfa) = BFA_FALSE;
5858 	bfa_sm_set_state(dconf, bfa_dconf_sm_uninit);
5859 }
5860 
5861 static void
5862 bfa_dconf_init_cb(void *arg, bfa_status_t status)
5863 {
5864 	struct bfa_s *bfa = arg;
5865 	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5866 
5867 	if (status == BFA_STATUS_OK) {
5868 		bfa_dconf_read_data_valid(bfa) = BFA_TRUE;
5869 		if (dconf->dconf->hdr.signature != BFI_DCONF_SIGNATURE)
5870 			dconf->dconf->hdr.signature = BFI_DCONF_SIGNATURE;
5871 		if (dconf->dconf->hdr.version != BFI_DCONF_VERSION)
5872 			dconf->dconf->hdr.version = BFI_DCONF_VERSION;
5873 	}
5874 	bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
5875 	bfa_fsm_send_event(&bfa->iocfc, IOCFC_E_DCONF_DONE);
5876 }
5877 
5878 void
5879 bfa_dconf_modinit(struct bfa_s *bfa)
5880 {
5881 	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5882 	bfa_sm_send_event(dconf, BFA_DCONF_SM_INIT);
5883 }
5884 static void
5885 bfa_dconf_start(struct bfa_s *bfa)
5886 {
5887 }
5888 
5889 static void
5890 bfa_dconf_stop(struct bfa_s *bfa)
5891 {
5892 }
5893 
5894 static void bfa_dconf_timer(void *cbarg)
5895 {
5896 	struct bfa_dconf_mod_s *dconf = cbarg;
5897 	bfa_sm_send_event(dconf, BFA_DCONF_SM_TIMEOUT);
5898 }
5899 static void
5900 bfa_dconf_iocdisable(struct bfa_s *bfa)
5901 {
5902 	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5903 	bfa_sm_send_event(dconf, BFA_DCONF_SM_IOCDISABLE);
5904 }
5905 
5906 static void
5907 bfa_dconf_detach(struct bfa_s *bfa)
5908 {
5909 }
5910 
5911 static bfa_status_t
5912 bfa_dconf_flash_write(struct bfa_dconf_mod_s *dconf)
5913 {
5914 	bfa_status_t bfa_status;
5915 	bfa_trc(dconf->bfa, 0);
5916 
5917 	bfa_status = bfa_flash_update_part(BFA_FLASH(dconf->bfa),
5918 				BFA_FLASH_PART_DRV, dconf->instance,
5919 				dconf->dconf,  sizeof(struct bfa_dconf_s), 0,
5920 				bfa_dconf_cbfn, dconf);
5921 	if (bfa_status != BFA_STATUS_OK)
5922 		WARN_ON(bfa_status);
5923 	bfa_trc(dconf->bfa, bfa_status);
5924 
5925 	return bfa_status;
5926 }
5927 
5928 bfa_status_t
5929 bfa_dconf_update(struct bfa_s *bfa)
5930 {
5931 	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5932 	bfa_trc(dconf->bfa, 0);
5933 	if (bfa_sm_cmp_state(dconf, bfa_dconf_sm_iocdown_dirty))
5934 		return BFA_STATUS_FAILED;
5935 
5936 	if (dconf->min_cfg) {
5937 		bfa_trc(dconf->bfa, dconf->min_cfg);
5938 		return BFA_STATUS_FAILED;
5939 	}
5940 
5941 	bfa_sm_send_event(dconf, BFA_DCONF_SM_WR);
5942 	return BFA_STATUS_OK;
5943 }
5944 
5945 static void
5946 bfa_dconf_cbfn(void *arg, bfa_status_t status)
5947 {
5948 	struct bfa_dconf_mod_s *dconf = arg;
5949 	WARN_ON(status);
5950 	bfa_sm_send_event(dconf, BFA_DCONF_SM_FLASH_COMP);
5951 }
5952 
5953 void
5954 bfa_dconf_modexit(struct bfa_s *bfa)
5955 {
5956 	struct bfa_dconf_mod_s *dconf = BFA_DCONF_MOD(bfa);
5957 	bfa_sm_send_event(dconf, BFA_DCONF_SM_EXIT);
5958 }
5959 
5960 /*
5961  * FRU specific functions
5962  */
5963 
5964 #define BFA_FRU_DMA_BUF_SZ	0x02000		/* 8k dma buffer */
5965 #define BFA_FRU_CHINOOK_MAX_SIZE 0x10000
5966 #define BFA_FRU_LIGHTNING_MAX_SIZE 0x200
5967 
5968 static void
5969 bfa_fru_notify(void *cbarg, enum bfa_ioc_event_e event)
5970 {
5971 	struct bfa_fru_s *fru = cbarg;
5972 
5973 	bfa_trc(fru, event);
5974 
5975 	switch (event) {
5976 	case BFA_IOC_E_DISABLED:
5977 	case BFA_IOC_E_FAILED:
5978 		if (fru->op_busy) {
5979 			fru->status = BFA_STATUS_IOC_FAILURE;
5980 			fru->cbfn(fru->cbarg, fru->status);
5981 			fru->op_busy = 0;
5982 		}
5983 		break;
5984 
5985 	default:
5986 		break;
5987 	}
5988 }
5989 
5990 /*
5991  * Send fru write request.
5992  *
5993  * @param[in] cbarg - callback argument
5994  */
5995 static void
5996 bfa_fru_write_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
5997 {
5998 	struct bfa_fru_s *fru = cbarg;
5999 	struct bfi_fru_write_req_s *msg =
6000 			(struct bfi_fru_write_req_s *) fru->mb.msg;
6001 	u32 len;
6002 
6003 	msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
6004 	len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
6005 				fru->residue : BFA_FRU_DMA_BUF_SZ;
6006 	msg->length = cpu_to_be32(len);
6007 
6008 	/*
6009 	 * indicate if it's the last msg of the whole write operation
6010 	 */
6011 	msg->last = (len == fru->residue) ? 1 : 0;
6012 
6013 	bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
6014 	bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
6015 
6016 	memcpy(fru->dbuf_kva, fru->ubuf + fru->offset, len);
6017 	bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
6018 
6019 	fru->residue -= len;
6020 	fru->offset += len;
6021 }
6022 
6023 /*
6024  * Send fru read request.
6025  *
6026  * @param[in] cbarg - callback argument
6027  */
6028 static void
6029 bfa_fru_read_send(void *cbarg, enum bfi_fru_h2i_msgs msg_type)
6030 {
6031 	struct bfa_fru_s *fru = cbarg;
6032 	struct bfi_fru_read_req_s *msg =
6033 			(struct bfi_fru_read_req_s *) fru->mb.msg;
6034 	u32 len;
6035 
6036 	msg->offset = cpu_to_be32(fru->addr_off + fru->offset);
6037 	len = (fru->residue < BFA_FRU_DMA_BUF_SZ) ?
6038 				fru->residue : BFA_FRU_DMA_BUF_SZ;
6039 	msg->length = cpu_to_be32(len);
6040 	bfi_h2i_set(msg->mh, BFI_MC_FRU, msg_type, bfa_ioc_portid(fru->ioc));
6041 	bfa_alen_set(&msg->alen, len, fru->dbuf_pa);
6042 	bfa_ioc_mbox_queue(fru->ioc, &fru->mb);
6043 }
6044 
6045 /*
6046  * Flash memory info API.
6047  *
6048  * @param[in] mincfg - minimal cfg variable
6049  */
6050 u32
6051 bfa_fru_meminfo(bfa_boolean_t mincfg)
6052 {
6053 	/* min driver doesn't need fru */
6054 	if (mincfg)
6055 		return 0;
6056 
6057 	return BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6058 }
6059 
6060 /*
6061  * Flash attach API.
6062  *
6063  * @param[in] fru - fru structure
6064  * @param[in] ioc  - ioc structure
6065  * @param[in] dev  - device structure
6066  * @param[in] trcmod - trace module
6067  * @param[in] logmod - log module
6068  */
6069 void
6070 bfa_fru_attach(struct bfa_fru_s *fru, struct bfa_ioc_s *ioc, void *dev,
6071 	struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg)
6072 {
6073 	fru->ioc = ioc;
6074 	fru->trcmod = trcmod;
6075 	fru->cbfn = NULL;
6076 	fru->cbarg = NULL;
6077 	fru->op_busy = 0;
6078 
6079 	bfa_ioc_mbox_regisr(fru->ioc, BFI_MC_FRU, bfa_fru_intr, fru);
6080 	bfa_q_qe_init(&fru->ioc_notify);
6081 	bfa_ioc_notify_init(&fru->ioc_notify, bfa_fru_notify, fru);
6082 	list_add_tail(&fru->ioc_notify.qe, &fru->ioc->notify_q);
6083 
6084 	/* min driver doesn't need fru */
6085 	if (mincfg) {
6086 		fru->dbuf_kva = NULL;
6087 		fru->dbuf_pa = 0;
6088 	}
6089 }
6090 
6091 /*
6092  * Claim memory for fru
6093  *
6094  * @param[in] fru - fru structure
6095  * @param[in] dm_kva - pointer to virtual memory address
6096  * @param[in] dm_pa - frusical memory address
6097  * @param[in] mincfg - minimal cfg variable
6098  */
6099 void
6100 bfa_fru_memclaim(struct bfa_fru_s *fru, u8 *dm_kva, u64 dm_pa,
6101 	bfa_boolean_t mincfg)
6102 {
6103 	if (mincfg)
6104 		return;
6105 
6106 	fru->dbuf_kva = dm_kva;
6107 	fru->dbuf_pa = dm_pa;
6108 	memset(fru->dbuf_kva, 0, BFA_FRU_DMA_BUF_SZ);
6109 	dm_kva += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6110 	dm_pa += BFA_ROUNDUP(BFA_FRU_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
6111 }
6112 
6113 /*
6114  * Update fru vpd image.
6115  *
6116  * @param[in] fru - fru structure
6117  * @param[in] buf - update data buffer
6118  * @param[in] len - data buffer length
6119  * @param[in] offset - offset relative to starting address
6120  * @param[in] cbfn - callback function
6121  * @param[in] cbarg - callback argument
6122  *
6123  * Return status.
6124  */
6125 bfa_status_t
6126 bfa_fruvpd_update(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6127 		  bfa_cb_fru_t cbfn, void *cbarg)
6128 {
6129 	bfa_trc(fru, BFI_FRUVPD_H2I_WRITE_REQ);
6130 	bfa_trc(fru, len);
6131 	bfa_trc(fru, offset);
6132 
6133 	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6134 		return BFA_STATUS_FRU_NOT_PRESENT;
6135 
6136 	if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
6137 		return BFA_STATUS_CMD_NOTSUPP;
6138 
6139 	if (!bfa_ioc_is_operational(fru->ioc))
6140 		return BFA_STATUS_IOC_NON_OP;
6141 
6142 	if (fru->op_busy) {
6143 		bfa_trc(fru, fru->op_busy);
6144 		return BFA_STATUS_DEVBUSY;
6145 	}
6146 
6147 	fru->op_busy = 1;
6148 
6149 	fru->cbfn = cbfn;
6150 	fru->cbarg = cbarg;
6151 	fru->residue = len;
6152 	fru->offset = 0;
6153 	fru->addr_off = offset;
6154 	fru->ubuf = buf;
6155 
6156 	bfa_fru_write_send(fru, BFI_FRUVPD_H2I_WRITE_REQ);
6157 
6158 	return BFA_STATUS_OK;
6159 }
6160 
6161 /*
6162  * Read fru vpd image.
6163  *
6164  * @param[in] fru - fru structure
6165  * @param[in] buf - read data buffer
6166  * @param[in] len - data buffer length
6167  * @param[in] offset - offset relative to starting address
6168  * @param[in] cbfn - callback function
6169  * @param[in] cbarg - callback argument
6170  *
6171  * Return status.
6172  */
6173 bfa_status_t
6174 bfa_fruvpd_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6175 		bfa_cb_fru_t cbfn, void *cbarg)
6176 {
6177 	bfa_trc(fru, BFI_FRUVPD_H2I_READ_REQ);
6178 	bfa_trc(fru, len);
6179 	bfa_trc(fru, offset);
6180 
6181 	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6182 		return BFA_STATUS_FRU_NOT_PRESENT;
6183 
6184 	if (fru->ioc->attr->card_type != BFA_MFG_TYPE_CHINOOK)
6185 		return BFA_STATUS_CMD_NOTSUPP;
6186 
6187 	if (!bfa_ioc_is_operational(fru->ioc))
6188 		return BFA_STATUS_IOC_NON_OP;
6189 
6190 	if (fru->op_busy) {
6191 		bfa_trc(fru, fru->op_busy);
6192 		return BFA_STATUS_DEVBUSY;
6193 	}
6194 
6195 	fru->op_busy = 1;
6196 
6197 	fru->cbfn = cbfn;
6198 	fru->cbarg = cbarg;
6199 	fru->residue = len;
6200 	fru->offset = 0;
6201 	fru->addr_off = offset;
6202 	fru->ubuf = buf;
6203 	bfa_fru_read_send(fru, BFI_FRUVPD_H2I_READ_REQ);
6204 
6205 	return BFA_STATUS_OK;
6206 }
6207 
6208 /*
6209  * Get maximum size fru vpd image.
6210  *
6211  * @param[in] fru - fru structure
6212  * @param[out] size - maximum size of fru vpd data
6213  *
6214  * Return status.
6215  */
6216 bfa_status_t
6217 bfa_fruvpd_get_max_size(struct bfa_fru_s *fru, u32 *max_size)
6218 {
6219 	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6220 		return BFA_STATUS_FRU_NOT_PRESENT;
6221 
6222 	if (!bfa_ioc_is_operational(fru->ioc))
6223 		return BFA_STATUS_IOC_NON_OP;
6224 
6225 	if (fru->ioc->attr->card_type == BFA_MFG_TYPE_CHINOOK)
6226 		*max_size = BFA_FRU_CHINOOK_MAX_SIZE;
6227 	else
6228 		return BFA_STATUS_CMD_NOTSUPP;
6229 	return BFA_STATUS_OK;
6230 }
6231 /*
6232  * tfru write.
6233  *
6234  * @param[in] fru - fru structure
6235  * @param[in] buf - update data buffer
6236  * @param[in] len - data buffer length
6237  * @param[in] offset - offset relative to starting address
6238  * @param[in] cbfn - callback function
6239  * @param[in] cbarg - callback argument
6240  *
6241  * Return status.
6242  */
6243 bfa_status_t
6244 bfa_tfru_write(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6245 	       bfa_cb_fru_t cbfn, void *cbarg)
6246 {
6247 	bfa_trc(fru, BFI_TFRU_H2I_WRITE_REQ);
6248 	bfa_trc(fru, len);
6249 	bfa_trc(fru, offset);
6250 	bfa_trc(fru, *((u8 *) buf));
6251 
6252 	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6253 		return BFA_STATUS_FRU_NOT_PRESENT;
6254 
6255 	if (!bfa_ioc_is_operational(fru->ioc))
6256 		return BFA_STATUS_IOC_NON_OP;
6257 
6258 	if (fru->op_busy) {
6259 		bfa_trc(fru, fru->op_busy);
6260 		return BFA_STATUS_DEVBUSY;
6261 	}
6262 
6263 	fru->op_busy = 1;
6264 
6265 	fru->cbfn = cbfn;
6266 	fru->cbarg = cbarg;
6267 	fru->residue = len;
6268 	fru->offset = 0;
6269 	fru->addr_off = offset;
6270 	fru->ubuf = buf;
6271 
6272 	bfa_fru_write_send(fru, BFI_TFRU_H2I_WRITE_REQ);
6273 
6274 	return BFA_STATUS_OK;
6275 }
6276 
6277 /*
6278  * tfru read.
6279  *
6280  * @param[in] fru - fru structure
6281  * @param[in] buf - read data buffer
6282  * @param[in] len - data buffer length
6283  * @param[in] offset - offset relative to starting address
6284  * @param[in] cbfn - callback function
6285  * @param[in] cbarg - callback argument
6286  *
6287  * Return status.
6288  */
6289 bfa_status_t
6290 bfa_tfru_read(struct bfa_fru_s *fru, void *buf, u32 len, u32 offset,
6291 	      bfa_cb_fru_t cbfn, void *cbarg)
6292 {
6293 	bfa_trc(fru, BFI_TFRU_H2I_READ_REQ);
6294 	bfa_trc(fru, len);
6295 	bfa_trc(fru, offset);
6296 
6297 	if (fru->ioc->asic_gen != BFI_ASIC_GEN_CT2)
6298 		return BFA_STATUS_FRU_NOT_PRESENT;
6299 
6300 	if (!bfa_ioc_is_operational(fru->ioc))
6301 		return BFA_STATUS_IOC_NON_OP;
6302 
6303 	if (fru->op_busy) {
6304 		bfa_trc(fru, fru->op_busy);
6305 		return BFA_STATUS_DEVBUSY;
6306 	}
6307 
6308 	fru->op_busy = 1;
6309 
6310 	fru->cbfn = cbfn;
6311 	fru->cbarg = cbarg;
6312 	fru->residue = len;
6313 	fru->offset = 0;
6314 	fru->addr_off = offset;
6315 	fru->ubuf = buf;
6316 	bfa_fru_read_send(fru, BFI_TFRU_H2I_READ_REQ);
6317 
6318 	return BFA_STATUS_OK;
6319 }
6320 
6321 /*
6322  * Process fru response messages upon receiving interrupts.
6323  *
6324  * @param[in] fruarg - fru structure
6325  * @param[in] msg - message structure
6326  */
6327 void
6328 bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)
6329 {
6330 	struct bfa_fru_s *fru = fruarg;
6331 	struct bfi_fru_rsp_s *rsp = (struct bfi_fru_rsp_s *)msg;
6332 	u32 status;
6333 
6334 	bfa_trc(fru, msg->mh.msg_id);
6335 
6336 	if (!fru->op_busy) {
6337 		/*
6338 		 * receiving response after ioc failure
6339 		 */
6340 		bfa_trc(fru, 0x9999);
6341 		return;
6342 	}
6343 
6344 	switch (msg->mh.msg_id) {
6345 	case BFI_FRUVPD_I2H_WRITE_RSP:
6346 	case BFI_TFRU_I2H_WRITE_RSP:
6347 		status = be32_to_cpu(rsp->status);
6348 		bfa_trc(fru, status);
6349 
6350 		if (status != BFA_STATUS_OK || fru->residue == 0) {
6351 			fru->status = status;
6352 			fru->op_busy = 0;
6353 			if (fru->cbfn)
6354 				fru->cbfn(fru->cbarg, fru->status);
6355 		} else {
6356 			bfa_trc(fru, fru->offset);
6357 			if (msg->mh.msg_id == BFI_FRUVPD_I2H_WRITE_RSP)
6358 				bfa_fru_write_send(fru,
6359 					BFI_FRUVPD_H2I_WRITE_REQ);
6360 			else
6361 				bfa_fru_write_send(fru,
6362 					BFI_TFRU_H2I_WRITE_REQ);
6363 		}
6364 		break;
6365 	case BFI_FRUVPD_I2H_READ_RSP:
6366 	case BFI_TFRU_I2H_READ_RSP:
6367 		status = be32_to_cpu(rsp->status);
6368 		bfa_trc(fru, status);
6369 
6370 		if (status != BFA_STATUS_OK) {
6371 			fru->status = status;
6372 			fru->op_busy = 0;
6373 			if (fru->cbfn)
6374 				fru->cbfn(fru->cbarg, fru->status);
6375 		} else {
6376 			u32 len = be32_to_cpu(rsp->length);
6377 
6378 			bfa_trc(fru, fru->offset);
6379 			bfa_trc(fru, len);
6380 
6381 			memcpy(fru->ubuf + fru->offset, fru->dbuf_kva, len);
6382 			fru->residue -= len;
6383 			fru->offset += len;
6384 
6385 			if (fru->residue == 0) {
6386 				fru->status = status;
6387 				fru->op_busy = 0;
6388 				if (fru->cbfn)
6389 					fru->cbfn(fru->cbarg, fru->status);
6390 			} else {
6391 				if (msg->mh.msg_id == BFI_FRUVPD_I2H_READ_RSP)
6392 					bfa_fru_read_send(fru,
6393 						BFI_FRUVPD_H2I_READ_REQ);
6394 				else
6395 					bfa_fru_read_send(fru,
6396 						BFI_TFRU_H2I_READ_REQ);
6397 			}
6398 		}
6399 		break;
6400 	default:
6401 		WARN_ON(1);
6402 	}
6403 }
6404