xref: /openbmc/linux/drivers/scsi/bfa/bfa_ioc.c (revision b6dcefde)
1 /*
2  * Copyright (c) 2005-2009 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 <bfa.h>
19 #include <bfa_ioc.h>
20 #include <bfa_fwimg_priv.h>
21 #include <bfa_trcmod_priv.h>
22 #include <cs/bfa_debug.h>
23 #include <bfi/bfi_ioc.h>
24 #include <bfi/bfi_ctreg.h>
25 #include <aen/bfa_aen_ioc.h>
26 #include <aen/bfa_aen.h>
27 #include <log/bfa_log_hal.h>
28 #include <defs/bfa_defs_pci.h>
29 
30 BFA_TRC_FILE(HAL, IOC);
31 
32 /**
33  * IOC local definitions
34  */
35 #define BFA_IOC_TOV		2000	/* msecs */
36 #define BFA_IOC_HB_TOV		1000	/* msecs */
37 #define BFA_IOC_HB_FAIL_MAX	4
38 #define BFA_IOC_HWINIT_MAX	2
39 #define BFA_IOC_FWIMG_MINSZ     (16 * 1024)
40 #define BFA_IOC_TOV_RECOVER	(BFA_IOC_HB_FAIL_MAX * BFA_IOC_HB_TOV \
41 				+ BFA_IOC_TOV)
42 
43 #define bfa_ioc_timer_start(__ioc)					\
44 	bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer,	\
45 			bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
46 #define bfa_ioc_timer_stop(__ioc)   bfa_timer_stop(&(__ioc)->ioc_timer)
47 
48 #define BFA_DBG_FWTRC_ENTS	(BFI_IOC_TRC_ENTS)
49 #define BFA_DBG_FWTRC_LEN					\
50 	(BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) +	\
51 	 (sizeof(struct bfa_trc_mod_s) -			\
52 	  BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
53 #define BFA_DBG_FWTRC_OFF(_fn)	(BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
54 #define bfa_ioc_stats(_ioc, _stats)	((_ioc)->stats._stats++)
55 
56 #define BFA_FLASH_CHUNK_NO(off)         (off / BFI_FLASH_CHUNK_SZ_WORDS)
57 #define BFA_FLASH_OFFSET_IN_CHUNK(off)  (off % BFI_FLASH_CHUNK_SZ_WORDS)
58 #define BFA_FLASH_CHUNK_ADDR(chunkno)   (chunkno * BFI_FLASH_CHUNK_SZ_WORDS)
59 bfa_boolean_t   bfa_auto_recover = BFA_FALSE;
60 
61 /*
62  * forward declarations
63  */
64 static void     bfa_ioc_aen_post(struct bfa_ioc_s *bfa,
65 				 enum bfa_ioc_aen_event event);
66 static void     bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
67 static void     bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc);
68 static void     bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
69 static void     bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
70 static void     bfa_ioc_timeout(void *ioc);
71 static void     bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
72 static void     bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
73 static void     bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
74 static void     bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
75 static void     bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
76 static void     bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
77 static void     bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
78 static void     bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
79 static void     bfa_ioc_recover(struct bfa_ioc_s *ioc);
80 static bfa_boolean_t bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc);
81 static void     bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc);
82 static void     bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
83 static void     bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
84 
85 /**
86  *  bfa_ioc_sm
87  */
88 
89 /**
90  * IOC state machine events
91  */
92 enum ioc_event {
93 	IOC_E_ENABLE = 1,	/*  IOC enable request */
94 	IOC_E_DISABLE = 2,	/*  IOC disable request */
95 	IOC_E_TIMEOUT = 3,	/*  f/w response timeout */
96 	IOC_E_FWREADY = 4,	/*  f/w initialization done */
97 	IOC_E_FWRSP_GETATTR = 5,	/*  IOC get attribute response */
98 	IOC_E_FWRSP_ENABLE = 6,	/*  enable f/w response */
99 	IOC_E_FWRSP_DISABLE = 7,	/*  disable f/w response */
100 	IOC_E_HBFAIL = 8,	/*  heartbeat failure */
101 	IOC_E_HWERROR = 9,	/*  hardware error interrupt */
102 	IOC_E_SEMLOCKED = 10,	/*  h/w semaphore is locked */
103 	IOC_E_DETACH = 11,	/*  driver detach cleanup */
104 };
105 
106 bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
107 bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event);
108 bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event);
109 bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event);
110 bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event);
111 bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
112 bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
113 bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
114 bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
115 bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event);
116 bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
117 bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
118 
119 static struct bfa_sm_table_s ioc_sm_table[] = {
120 	{BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
121 	{BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
122 	{BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
123 	{BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
124 	{BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
125 	{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
126 	{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
127 	{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
128 	{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
129 	{BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
130 	{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
131 	{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
132 };
133 
134 /**
135  * Reset entry actions -- initialize state machine
136  */
137 static void
138 bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
139 {
140 	ioc->retry_count = 0;
141 	ioc->auto_recover = bfa_auto_recover;
142 }
143 
144 /**
145  * Beginning state. IOC is in reset state.
146  */
147 static void
148 bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
149 {
150 	bfa_trc(ioc, event);
151 
152 	switch (event) {
153 	case IOC_E_ENABLE:
154 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
155 		break;
156 
157 	case IOC_E_DISABLE:
158 		bfa_ioc_disable_comp(ioc);
159 		break;
160 
161 	case IOC_E_DETACH:
162 		break;
163 
164 	default:
165 		bfa_sm_fault(ioc, event);
166 	}
167 }
168 
169 /**
170  * Semaphore should be acquired for version check.
171  */
172 static void
173 bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc)
174 {
175 	bfa_ioc_hw_sem_get(ioc);
176 }
177 
178 /**
179  * Awaiting h/w semaphore to continue with version check.
180  */
181 static void
182 bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event)
183 {
184 	bfa_trc(ioc, event);
185 
186 	switch (event) {
187 	case IOC_E_SEMLOCKED:
188 		if (bfa_ioc_firmware_lock(ioc)) {
189 			ioc->retry_count = 0;
190 			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
191 		} else {
192 			bfa_ioc_hw_sem_release(ioc);
193 			bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
194 		}
195 		break;
196 
197 	case IOC_E_DISABLE:
198 		bfa_ioc_disable_comp(ioc);
199 		/*
200 		 * fall through
201 		 */
202 
203 	case IOC_E_DETACH:
204 		bfa_ioc_hw_sem_get_cancel(ioc);
205 		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
206 		break;
207 
208 	case IOC_E_FWREADY:
209 		break;
210 
211 	default:
212 		bfa_sm_fault(ioc, event);
213 	}
214 }
215 
216 /**
217  * Notify enable completion callback and generate mismatch AEN.
218  */
219 static void
220 bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc)
221 {
222 	/**
223 	 * Provide enable completion callback and AEN notification only once.
224 	 */
225 	if (ioc->retry_count == 0) {
226 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
227 		bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH);
228 	}
229 	ioc->retry_count++;
230 	bfa_ioc_timer_start(ioc);
231 }
232 
233 /**
234  * Awaiting firmware version match.
235  */
236 static void
237 bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event)
238 {
239 	bfa_trc(ioc, event);
240 
241 	switch (event) {
242 	case IOC_E_TIMEOUT:
243 		bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
244 		break;
245 
246 	case IOC_E_DISABLE:
247 		bfa_ioc_disable_comp(ioc);
248 		/*
249 		 * fall through
250 		 */
251 
252 	case IOC_E_DETACH:
253 		bfa_ioc_timer_stop(ioc);
254 		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
255 		break;
256 
257 	case IOC_E_FWREADY:
258 		break;
259 
260 	default:
261 		bfa_sm_fault(ioc, event);
262 	}
263 }
264 
265 /**
266  * Request for semaphore.
267  */
268 static void
269 bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc)
270 {
271 	bfa_ioc_hw_sem_get(ioc);
272 }
273 
274 /**
275  * Awaiting semaphore for h/w initialzation.
276  */
277 static void
278 bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event)
279 {
280 	bfa_trc(ioc, event);
281 
282 	switch (event) {
283 	case IOC_E_SEMLOCKED:
284 		ioc->retry_count = 0;
285 		bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
286 		break;
287 
288 	case IOC_E_DISABLE:
289 		bfa_ioc_hw_sem_get_cancel(ioc);
290 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
291 		break;
292 
293 	default:
294 		bfa_sm_fault(ioc, event);
295 	}
296 }
297 
298 
299 static void
300 bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc)
301 {
302 	bfa_ioc_timer_start(ioc);
303 	bfa_ioc_reset(ioc, BFA_FALSE);
304 }
305 
306 /**
307  * Hardware is being initialized. Interrupts are enabled.
308  * Holding hardware semaphore lock.
309  */
310 static void
311 bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event)
312 {
313 	bfa_trc(ioc, event);
314 
315 	switch (event) {
316 	case IOC_E_FWREADY:
317 		bfa_ioc_timer_stop(ioc);
318 		bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
319 		break;
320 
321 	case IOC_E_HWERROR:
322 		bfa_ioc_timer_stop(ioc);
323 		/*
324 		 * fall through
325 		 */
326 
327 	case IOC_E_TIMEOUT:
328 		ioc->retry_count++;
329 		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
330 			bfa_ioc_timer_start(ioc);
331 			bfa_ioc_reset(ioc, BFA_TRUE);
332 			break;
333 		}
334 
335 		bfa_ioc_hw_sem_release(ioc);
336 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
337 		break;
338 
339 	case IOC_E_DISABLE:
340 		bfa_ioc_hw_sem_release(ioc);
341 		bfa_ioc_timer_stop(ioc);
342 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
343 		break;
344 
345 	default:
346 		bfa_sm_fault(ioc, event);
347 	}
348 }
349 
350 
351 static void
352 bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
353 {
354 	bfa_ioc_timer_start(ioc);
355 	bfa_ioc_send_enable(ioc);
356 }
357 
358 /**
359  * Host IOC function is being enabled, awaiting response from firmware.
360  * Semaphore is acquired.
361  */
362 static void
363 bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
364 {
365 	bfa_trc(ioc, event);
366 
367 	switch (event) {
368 	case IOC_E_FWRSP_ENABLE:
369 		bfa_ioc_timer_stop(ioc);
370 		bfa_ioc_hw_sem_release(ioc);
371 		bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
372 		break;
373 
374 	case IOC_E_HWERROR:
375 		bfa_ioc_timer_stop(ioc);
376 		/*
377 		 * fall through
378 		 */
379 
380 	case IOC_E_TIMEOUT:
381 		ioc->retry_count++;
382 		if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
383 			bfa_reg_write(ioc->ioc_regs.ioc_fwstate,
384 				      BFI_IOC_UNINIT);
385 			bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
386 			break;
387 		}
388 
389 		bfa_ioc_hw_sem_release(ioc);
390 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
391 		break;
392 
393 	case IOC_E_DISABLE:
394 		bfa_ioc_timer_stop(ioc);
395 		bfa_ioc_hw_sem_release(ioc);
396 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
397 		break;
398 
399 	case IOC_E_FWREADY:
400 		bfa_ioc_send_enable(ioc);
401 		break;
402 
403 	default:
404 		bfa_sm_fault(ioc, event);
405 	}
406 }
407 
408 
409 static void
410 bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
411 {
412 	bfa_ioc_timer_start(ioc);
413 	bfa_ioc_send_getattr(ioc);
414 }
415 
416 /**
417  * IOC configuration in progress. Timer is active.
418  */
419 static void
420 bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
421 {
422 	bfa_trc(ioc, event);
423 
424 	switch (event) {
425 	case IOC_E_FWRSP_GETATTR:
426 		bfa_ioc_timer_stop(ioc);
427 		bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
428 		break;
429 
430 	case IOC_E_HWERROR:
431 		bfa_ioc_timer_stop(ioc);
432 		/*
433 		 * fall through
434 		 */
435 
436 	case IOC_E_TIMEOUT:
437 		bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
438 		break;
439 
440 	case IOC_E_DISABLE:
441 		bfa_ioc_timer_stop(ioc);
442 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
443 		break;
444 
445 	default:
446 		bfa_sm_fault(ioc, event);
447 	}
448 }
449 
450 
451 static void
452 bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
453 {
454 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
455 	bfa_ioc_hb_monitor(ioc);
456 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE);
457 }
458 
459 static void
460 bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
461 {
462 	bfa_trc(ioc, event);
463 
464 	switch (event) {
465 	case IOC_E_ENABLE:
466 		break;
467 
468 	case IOC_E_DISABLE:
469 		bfa_ioc_hb_stop(ioc);
470 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
471 		break;
472 
473 	case IOC_E_HWERROR:
474 	case IOC_E_FWREADY:
475 		/**
476 		 * Hard error or IOC recovery by other function.
477 		 * Treat it same as heartbeat failure.
478 		 */
479 		bfa_ioc_hb_stop(ioc);
480 		/*
481 		 * !!! fall through !!!
482 		 */
483 
484 	case IOC_E_HBFAIL:
485 		bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
486 		break;
487 
488 	default:
489 		bfa_sm_fault(ioc, event);
490 	}
491 }
492 
493 
494 static void
495 bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
496 {
497 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE);
498 	bfa_ioc_timer_start(ioc);
499 	bfa_ioc_send_disable(ioc);
500 }
501 
502 /**
503  * IOC is being disabled
504  */
505 static void
506 bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
507 {
508 	bfa_trc(ioc, event);
509 
510 	switch (event) {
511 	case IOC_E_HWERROR:
512 	case IOC_E_FWRSP_DISABLE:
513 		bfa_ioc_timer_stop(ioc);
514 		/*
515 		 * !!! fall through !!!
516 		 */
517 
518 	case IOC_E_TIMEOUT:
519 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
520 		break;
521 
522 	default:
523 		bfa_sm_fault(ioc, event);
524 	}
525 }
526 
527 /**
528  * IOC disable completion entry.
529  */
530 static void
531 bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
532 {
533 	bfa_ioc_disable_comp(ioc);
534 }
535 
536 static void
537 bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
538 {
539 	bfa_trc(ioc, event);
540 
541 	switch (event) {
542 	case IOC_E_ENABLE:
543 		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
544 		break;
545 
546 	case IOC_E_DISABLE:
547 		ioc->cbfn->disable_cbfn(ioc->bfa);
548 		break;
549 
550 	case IOC_E_FWREADY:
551 		break;
552 
553 	case IOC_E_DETACH:
554 		bfa_ioc_firmware_unlock(ioc);
555 		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
556 		break;
557 
558 	default:
559 		bfa_sm_fault(ioc, event);
560 	}
561 }
562 
563 
564 static void
565 bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
566 {
567 	ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
568 	bfa_ioc_timer_start(ioc);
569 }
570 
571 /**
572  * Hardware initialization failed.
573  */
574 static void
575 bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
576 {
577 	bfa_trc(ioc, event);
578 
579 	switch (event) {
580 	case IOC_E_DISABLE:
581 		bfa_ioc_timer_stop(ioc);
582 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
583 		break;
584 
585 	case IOC_E_DETACH:
586 		bfa_ioc_timer_stop(ioc);
587 		bfa_ioc_firmware_unlock(ioc);
588 		bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
589 		break;
590 
591 	case IOC_E_TIMEOUT:
592 		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
593 		break;
594 
595 	default:
596 		bfa_sm_fault(ioc, event);
597 	}
598 }
599 
600 
601 static void
602 bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc)
603 {
604 	struct list_head *qe;
605 	struct bfa_ioc_hbfail_notify_s *notify;
606 
607 	/**
608 	 * Mark IOC as failed in hardware and stop firmware.
609 	 */
610 	bfa_ioc_lpu_stop(ioc);
611 	bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_HBFAIL);
612 
613 	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
614 		bfa_reg_write(ioc->ioc_regs.ll_halt, __FW_INIT_HALT_P);
615 		/*
616 		 * Wait for halt to take effect
617 		 */
618 		bfa_reg_read(ioc->ioc_regs.ll_halt);
619 	}
620 
621 	/**
622 	 * Notify driver and common modules registered for notification.
623 	 */
624 	ioc->cbfn->hbfail_cbfn(ioc->bfa);
625 	list_for_each(qe, &ioc->hb_notify_q) {
626 		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
627 		notify->cbfn(notify->cbarg);
628 	}
629 
630 	/**
631 	 * Flush any queued up mailbox requests.
632 	 */
633 	bfa_ioc_mbox_hbfail(ioc);
634 	bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL);
635 
636 	/**
637 	 * Trigger auto-recovery after a delay.
638 	 */
639 	if (ioc->auto_recover) {
640 		bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer,
641 				bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER);
642 	}
643 }
644 
645 /**
646  * IOC heartbeat failure.
647  */
648 static void
649 bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event)
650 {
651 	bfa_trc(ioc, event);
652 
653 	switch (event) {
654 
655 	case IOC_E_ENABLE:
656 		ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
657 		break;
658 
659 	case IOC_E_DISABLE:
660 		if (ioc->auto_recover)
661 			bfa_ioc_timer_stop(ioc);
662 		bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
663 		break;
664 
665 	case IOC_E_TIMEOUT:
666 		bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
667 		break;
668 
669 	case IOC_E_FWREADY:
670 		/**
671 		 * Recovery is already initiated by other function.
672 		 */
673 		break;
674 
675 	default:
676 		bfa_sm_fault(ioc, event);
677 	}
678 }
679 
680 
681 
682 /**
683  *  bfa_ioc_pvt BFA IOC private functions
684  */
685 
686 static void
687 bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
688 {
689 	struct list_head *qe;
690 	struct bfa_ioc_hbfail_notify_s *notify;
691 
692 	ioc->cbfn->disable_cbfn(ioc->bfa);
693 
694 	/**
695 	 * Notify common modules registered for notification.
696 	 */
697 	list_for_each(qe, &ioc->hb_notify_q) {
698 		notify = (struct bfa_ioc_hbfail_notify_s *)qe;
699 		notify->cbfn(notify->cbarg);
700 	}
701 }
702 
703 static void
704 bfa_ioc_sem_timeout(void *ioc_arg)
705 {
706 	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
707 
708 	bfa_ioc_hw_sem_get(ioc);
709 }
710 
711 static void
712 bfa_ioc_usage_sem_get(struct bfa_ioc_s *ioc)
713 {
714 	u32        r32;
715 	int             cnt = 0;
716 #define BFA_SEM_SPINCNT	1000
717 
718 	do {
719 		r32 = bfa_reg_read(ioc->ioc_regs.ioc_usage_sem_reg);
720 		cnt++;
721 		if (cnt > BFA_SEM_SPINCNT)
722 			break;
723 	} while (r32 != 0);
724 	bfa_assert(cnt < BFA_SEM_SPINCNT);
725 }
726 
727 static void
728 bfa_ioc_usage_sem_release(struct bfa_ioc_s *ioc)
729 {
730 	bfa_reg_write(ioc->ioc_regs.ioc_usage_sem_reg, 1);
731 }
732 
733 static void
734 bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
735 {
736 	u32        r32;
737 
738 	/**
739 	 * First read to the semaphore register will return 0, subsequent reads
740 	 * will return 1. Semaphore is released by writing 0 to the register
741 	 */
742 	r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg);
743 	if (r32 == 0) {
744 		bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
745 		return;
746 	}
747 
748 	bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout,
749 			ioc, BFA_IOC_TOV);
750 }
751 
752 static void
753 bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
754 {
755 	bfa_reg_write(ioc->ioc_regs.ioc_sem_reg, 1);
756 }
757 
758 static void
759 bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
760 {
761 	bfa_timer_stop(&ioc->sem_timer);
762 }
763 
764 /**
765  * Initialize LPU local memory (aka secondary memory / SRAM)
766  */
767 static void
768 bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
769 {
770 	u32        pss_ctl;
771 	int             i;
772 #define PSS_LMEM_INIT_TIME  10000
773 
774 	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
775 	pss_ctl &= ~__PSS_LMEM_RESET;
776 	pss_ctl |= __PSS_LMEM_INIT_EN;
777 	pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */
778 	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
779 
780 	/**
781 	 * wait for memory initialization to be complete
782 	 */
783 	i = 0;
784 	do {
785 		pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
786 		i++;
787 	} while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
788 
789 	/**
790 	 * If memory initialization is not successful, IOC timeout will catch
791 	 * such failures.
792 	 */
793 	bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
794 	bfa_trc(ioc, pss_ctl);
795 
796 	pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
797 	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
798 }
799 
800 static void
801 bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
802 {
803 	u32        pss_ctl;
804 
805 	/**
806 	 * Take processor out of reset.
807 	 */
808 	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
809 	pss_ctl &= ~__PSS_LPU0_RESET;
810 
811 	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
812 }
813 
814 static void
815 bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
816 {
817 	u32        pss_ctl;
818 
819 	/**
820 	 * Put processors in reset.
821 	 */
822 	pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg);
823 	pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
824 
825 	bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl);
826 }
827 
828 /**
829  * Get driver and firmware versions.
830  */
831 static void
832 bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
833 {
834 	u32        pgnum, pgoff;
835 	u32        loff = 0;
836 	int             i;
837 	u32       *fwsig = (u32 *) fwhdr;
838 
839 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
840 	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
841 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
842 
843 	for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
844 	     i++) {
845 		fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
846 		loff += sizeof(u32);
847 	}
848 }
849 
850 static u32 *
851 bfa_ioc_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off)
852 {
853 	if (ioc->ctdev)
854 		return bfi_image_ct_get_chunk(off);
855 	return bfi_image_cb_get_chunk(off);
856 }
857 
858 static          u32
859 bfa_ioc_fwimg_get_size(struct bfa_ioc_s *ioc)
860 {
861 return (ioc->ctdev) ? bfi_image_ct_size : bfi_image_cb_size;
862 }
863 
864 /**
865  * Returns TRUE if same.
866  */
867 static          bfa_boolean_t
868 bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
869 {
870 	struct bfi_ioc_image_hdr_s *drv_fwhdr;
871 	int             i;
872 
873 	drv_fwhdr =
874 		(struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0);
875 
876 	for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
877 		if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
878 			bfa_trc(ioc, i);
879 			bfa_trc(ioc, fwhdr->md5sum[i]);
880 			bfa_trc(ioc, drv_fwhdr->md5sum[i]);
881 			return BFA_FALSE;
882 		}
883 	}
884 
885 	bfa_trc(ioc, fwhdr->md5sum[0]);
886 	return BFA_TRUE;
887 }
888 
889 /**
890  * Return true if current running version is valid. Firmware signature and
891  * execution context (driver/bios) must match.
892  */
893 static          bfa_boolean_t
894 bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc)
895 {
896 	struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
897 
898 	/**
899 	 * If bios/efi boot (flash based) -- return true
900 	 */
901 	if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
902 		return BFA_TRUE;
903 
904 	bfa_ioc_fwver_get(ioc, &fwhdr);
905 	drv_fwhdr =
906 		(struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0);
907 
908 	if (fwhdr.signature != drv_fwhdr->signature) {
909 		bfa_trc(ioc, fwhdr.signature);
910 		bfa_trc(ioc, drv_fwhdr->signature);
911 		return BFA_FALSE;
912 	}
913 
914 	if (fwhdr.exec != drv_fwhdr->exec) {
915 		bfa_trc(ioc, fwhdr.exec);
916 		bfa_trc(ioc, drv_fwhdr->exec);
917 		return BFA_FALSE;
918 	}
919 
920 	return bfa_ioc_fwver_cmp(ioc, &fwhdr);
921 }
922 
923 /**
924  * Return true if firmware of current driver matches the running firmware.
925  */
926 static          bfa_boolean_t
927 bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc)
928 {
929 	enum bfi_ioc_state ioc_fwstate;
930 	u32        usecnt;
931 	struct bfi_ioc_image_hdr_s fwhdr;
932 
933 	/**
934 	 * Firmware match check is relevant only for CNA.
935 	 */
936 	if (!ioc->cna)
937 		return BFA_TRUE;
938 
939 	/**
940 	 * If bios boot (flash based) -- do not increment usage count
941 	 */
942 	if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
943 		return BFA_TRUE;
944 
945 	bfa_ioc_usage_sem_get(ioc);
946 	usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg);
947 
948 	/**
949 	 * If usage count is 0, always return TRUE.
950 	 */
951 	if (usecnt == 0) {
952 		bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 1);
953 		bfa_ioc_usage_sem_release(ioc);
954 		bfa_trc(ioc, usecnt);
955 		return BFA_TRUE;
956 	}
957 
958 	ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
959 	bfa_trc(ioc, ioc_fwstate);
960 
961 	/**
962 	 * Use count cannot be non-zero and chip in uninitialized state.
963 	 */
964 	bfa_assert(ioc_fwstate != BFI_IOC_UNINIT);
965 
966 	/**
967 	 * Check if another driver with a different firmware is active
968 	 */
969 	bfa_ioc_fwver_get(ioc, &fwhdr);
970 	if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) {
971 		bfa_ioc_usage_sem_release(ioc);
972 		bfa_trc(ioc, usecnt);
973 		return BFA_FALSE;
974 	}
975 
976 	/**
977 	 * Same firmware version. Increment the reference count.
978 	 */
979 	usecnt++;
980 	bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt);
981 	bfa_ioc_usage_sem_release(ioc);
982 	bfa_trc(ioc, usecnt);
983 	return BFA_TRUE;
984 }
985 
986 static void
987 bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc)
988 {
989 	u32        usecnt;
990 
991 	/**
992 	 * Firmware lock is relevant only for CNA.
993 	 * If bios boot (flash based) -- do not decrement usage count
994 	 */
995 	if (!ioc->cna || (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ))
996 		return;
997 
998 	/**
999 	 * decrement usage count
1000 	 */
1001 	bfa_ioc_usage_sem_get(ioc);
1002 	usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg);
1003 	bfa_assert(usecnt > 0);
1004 
1005 	usecnt--;
1006 	bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt);
1007 	bfa_trc(ioc, usecnt);
1008 
1009 	bfa_ioc_usage_sem_release(ioc);
1010 }
1011 
1012 /**
1013  * Conditionally flush any pending message from firmware at start.
1014  */
1015 static void
1016 bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1017 {
1018 	u32        r32;
1019 
1020 	r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
1021 	if (r32)
1022 		bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1);
1023 }
1024 
1025 
1026 static void
1027 bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1028 {
1029 	enum bfi_ioc_state ioc_fwstate;
1030 	bfa_boolean_t   fwvalid;
1031 
1032 	ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate);
1033 
1034 	if (force)
1035 		ioc_fwstate = BFI_IOC_UNINIT;
1036 
1037 	bfa_trc(ioc, ioc_fwstate);
1038 
1039 	/**
1040 	 * check if firmware is valid
1041 	 */
1042 	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
1043 			BFA_FALSE : bfa_ioc_fwver_valid(ioc);
1044 
1045 	if (!fwvalid) {
1046 		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
1047 		return;
1048 	}
1049 
1050 	/**
1051 	 * If hardware initialization is in progress (initialized by other IOC),
1052 	 * just wait for an initialization completion interrupt.
1053 	 */
1054 	if (ioc_fwstate == BFI_IOC_INITING) {
1055 		bfa_trc(ioc, ioc_fwstate);
1056 		ioc->cbfn->reset_cbfn(ioc->bfa);
1057 		return;
1058 	}
1059 
1060 	/**
1061 	 * If IOC function is disabled and firmware version is same,
1062 	 * just re-enable IOC.
1063 	 */
1064 	if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
1065 		bfa_trc(ioc, ioc_fwstate);
1066 
1067 		/**
1068 		 * When using MSI-X any pending firmware ready event should
1069 		 * be flushed. Otherwise MSI-X interrupts are not delivered.
1070 		 */
1071 		bfa_ioc_msgflush(ioc);
1072 		ioc->cbfn->reset_cbfn(ioc->bfa);
1073 		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
1074 		return;
1075 	}
1076 
1077 	/**
1078 	 * Initialize the h/w for any other states.
1079 	 */
1080 	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
1081 }
1082 
1083 static void
1084 bfa_ioc_timeout(void *ioc_arg)
1085 {
1086 	struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg;
1087 
1088 	bfa_trc(ioc, 0);
1089 	bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1090 }
1091 
1092 void
1093 bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1094 {
1095 	u32       *msgp = (u32 *) ioc_msg;
1096 	u32        i;
1097 
1098 	bfa_trc(ioc, msgp[0]);
1099 	bfa_trc(ioc, len);
1100 
1101 	bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
1102 
1103 	/*
1104 	 * first write msg to mailbox registers
1105 	 */
1106 	for (i = 0; i < len / sizeof(u32); i++)
1107 		bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32),
1108 			      bfa_os_wtole(msgp[i]));
1109 
1110 	for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
1111 		bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32), 0);
1112 
1113 	/*
1114 	 * write 1 to mailbox CMD to trigger LPU event
1115 	 */
1116 	bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1);
1117 	(void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
1118 }
1119 
1120 static void
1121 bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1122 {
1123 	struct bfi_ioc_ctrl_req_s enable_req;
1124 
1125 	bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1126 		    bfa_ioc_portid(ioc));
1127 	enable_req.ioc_class = ioc->ioc_mc;
1128 	bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1129 }
1130 
1131 static void
1132 bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1133 {
1134 	struct bfi_ioc_ctrl_req_s disable_req;
1135 
1136 	bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1137 		    bfa_ioc_portid(ioc));
1138 	bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1139 }
1140 
1141 static void
1142 bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1143 {
1144 	struct bfi_ioc_getattr_req_s attr_req;
1145 
1146 	bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1147 		    bfa_ioc_portid(ioc));
1148 	bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1149 	bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1150 }
1151 
1152 static void
1153 bfa_ioc_hb_check(void *cbarg)
1154 {
1155 	struct bfa_ioc_s *ioc = cbarg;
1156 	u32        hb_count;
1157 
1158 	hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
1159 	if (ioc->hb_count == hb_count) {
1160 		ioc->hb_fail++;
1161 	} else {
1162 		ioc->hb_count = hb_count;
1163 		ioc->hb_fail = 0;
1164 	}
1165 
1166 	if (ioc->hb_fail >= BFA_IOC_HB_FAIL_MAX) {
1167 		bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE, hb_count);
1168 		ioc->hb_fail = 0;
1169 		bfa_ioc_recover(ioc);
1170 		return;
1171 	}
1172 
1173 	bfa_ioc_mbox_poll(ioc);
1174 	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
1175 			BFA_IOC_HB_TOV);
1176 }
1177 
1178 static void
1179 bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1180 {
1181 	ioc->hb_fail = 0;
1182 	ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat);
1183 	bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc,
1184 			BFA_IOC_HB_TOV);
1185 }
1186 
1187 static void
1188 bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
1189 {
1190 	bfa_timer_stop(&ioc->ioc_timer);
1191 }
1192 
1193 /**
1194  * Host to LPU mailbox message addresses
1195  */
1196 static struct {
1197 	u32        hfn_mbox, lpu_mbox, hfn_pgn;
1198 } iocreg_fnreg[] = {
1199 	{
1200 	HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0}, {
1201 	HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1}, {
1202 	HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2}, {
1203 	HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3}
1204 };
1205 
1206 /**
1207  * Host <-> LPU mailbox command/status registers - port 0
1208  */
1209 static struct {
1210 	u32        hfn, lpu;
1211 } iocreg_mbcmd_p0[] = {
1212 	{
1213 	HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT}, {
1214 	HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT}, {
1215 	HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT}, {
1216 	HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT}
1217 };
1218 
1219 /**
1220  * Host <-> LPU mailbox command/status registers - port 1
1221  */
1222 static struct {
1223 	u32        hfn, lpu;
1224 } iocreg_mbcmd_p1[] = {
1225 	{
1226 	HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT}, {
1227 	HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT}, {
1228 	HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT}, {
1229 	HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT}
1230 };
1231 
1232 /**
1233  * Shared IRQ handling in INTX mode
1234  */
1235 static struct {
1236 	u32        isr, msk;
1237 } iocreg_shirq_next[] = {
1238 	{
1239 	HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK}, {
1240 	HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK}, {
1241 	HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK}, {
1242 HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK},};
1243 
1244 static void
1245 bfa_ioc_reg_init(struct bfa_ioc_s *ioc)
1246 {
1247 	bfa_os_addr_t   rb;
1248 	int             pcifn = bfa_ioc_pcifn(ioc);
1249 
1250 	rb = bfa_ioc_bar0(ioc);
1251 
1252 	ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox;
1253 	ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox;
1254 	ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn;
1255 
1256 	if (ioc->port_id == 0) {
1257 		ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG;
1258 		ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG;
1259 		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn;
1260 		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu;
1261 		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0;
1262 	} else {
1263 		ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG);
1264 		ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG);
1265 		ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn;
1266 		ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu;
1267 		ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1;
1268 	}
1269 
1270 	/**
1271 	 * Shared IRQ handling in INTX mode
1272 	 */
1273 	ioc->ioc_regs.shirq_isr_next = rb + iocreg_shirq_next[pcifn].isr;
1274 	ioc->ioc_regs.shirq_msk_next = rb + iocreg_shirq_next[pcifn].msk;
1275 
1276 	/*
1277 	 * PSS control registers
1278 	 */
1279 	ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG);
1280 	ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG);
1281 	ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG);
1282 
1283 	/*
1284 	 * IOC semaphore registers and serialization
1285 	 */
1286 	ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG);
1287 	ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG);
1288 	ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT);
1289 
1290 	/**
1291 	 * sram memory access
1292 	 */
1293 	ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START);
1294 	ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB;
1295 	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT)
1296 		ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT;
1297 }
1298 
1299 /**
1300  *      Initiate a full firmware download.
1301  */
1302 static void
1303 bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1304 		    u32 boot_param)
1305 {
1306 	u32       *fwimg;
1307 	u32        pgnum, pgoff;
1308 	u32        loff = 0;
1309 	u32        chunkno = 0;
1310 	u32        i;
1311 
1312 	/**
1313 	 * Initialize LMEM first before code download
1314 	 */
1315 	bfa_ioc_lmem_init(ioc);
1316 
1317 	/**
1318 	 * Flash based firmware boot
1319 	 */
1320 	bfa_trc(ioc, bfa_ioc_fwimg_get_size(ioc));
1321 	if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)
1322 		boot_type = BFI_BOOT_TYPE_FLASH;
1323 	fwimg = bfa_ioc_fwimg_get_chunk(ioc, chunkno);
1324 	fwimg[BFI_BOOT_TYPE_OFF / sizeof(u32)] = bfa_os_swap32(boot_type);
1325 	fwimg[BFI_BOOT_PARAM_OFF / sizeof(u32)] =
1326 		bfa_os_swap32(boot_param);
1327 
1328 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
1329 	pgoff = bfa_ioc_smem_pgoff(ioc, loff);
1330 
1331 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
1332 
1333 	for (i = 0; i < bfa_ioc_fwimg_get_size(ioc); i++) {
1334 
1335 		if (BFA_FLASH_CHUNK_NO(i) != chunkno) {
1336 			chunkno = BFA_FLASH_CHUNK_NO(i);
1337 			fwimg = bfa_ioc_fwimg_get_chunk(ioc,
1338 					BFA_FLASH_CHUNK_ADDR(chunkno));
1339 		}
1340 
1341 		/**
1342 		 * write smem
1343 		 */
1344 		bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
1345 			      fwimg[BFA_FLASH_OFFSET_IN_CHUNK(i)]);
1346 
1347 		loff += sizeof(u32);
1348 
1349 		/**
1350 		 * handle page offset wrap around
1351 		 */
1352 		loff = PSS_SMEM_PGOFF(loff);
1353 		if (loff == 0) {
1354 			pgnum++;
1355 			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
1356 		}
1357 	}
1358 
1359 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
1360 		      bfa_ioc_smem_pgnum(ioc, 0));
1361 }
1362 
1363 static void
1364 bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1365 {
1366 	bfa_ioc_hwinit(ioc, force);
1367 }
1368 
1369 /**
1370  * Update BFA configuration from firmware configuration.
1371  */
1372 static void
1373 bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1374 {
1375 	struct bfi_ioc_attr_s *attr = ioc->attr;
1376 
1377 	attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop);
1378 	attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize);
1379 
1380 	bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1381 }
1382 
1383 /**
1384  * Attach time initialization of mbox logic.
1385  */
1386 static void
1387 bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1388 {
1389 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1390 	int             mc;
1391 
1392 	INIT_LIST_HEAD(&mod->cmd_q);
1393 	for (mc = 0; mc < BFI_MC_MAX; mc++) {
1394 		mod->mbhdlr[mc].cbfn = NULL;
1395 		mod->mbhdlr[mc].cbarg = ioc->bfa;
1396 	}
1397 }
1398 
1399 /**
1400  * Mbox poll timer -- restarts any pending mailbox requests.
1401  */
1402 static void
1403 bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1404 {
1405 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1406 	struct bfa_mbox_cmd_s *cmd;
1407 	u32        stat;
1408 
1409 	/**
1410 	 * If no command pending, do nothing
1411 	 */
1412 	if (list_empty(&mod->cmd_q))
1413 		return;
1414 
1415 	/**
1416 	 * If previous command is not yet fetched by firmware, do nothing
1417 	 */
1418 	stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
1419 	if (stat)
1420 		return;
1421 
1422 	/**
1423 	 * Enqueue command to firmware.
1424 	 */
1425 	bfa_q_deq(&mod->cmd_q, &cmd);
1426 	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1427 }
1428 
1429 /**
1430  * Cleanup any pending requests.
1431  */
1432 static void
1433 bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
1434 {
1435 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1436 	struct bfa_mbox_cmd_s *cmd;
1437 
1438 	while (!list_empty(&mod->cmd_q))
1439 		bfa_q_deq(&mod->cmd_q, &cmd);
1440 }
1441 
1442 /**
1443  * Initialize IOC to port mapping.
1444  */
1445 
1446 #define FNC_PERS_FN_SHIFT(__fn)	((__fn) * 8)
1447 static void
1448 bfa_ioc_map_port(struct bfa_ioc_s *ioc)
1449 {
1450 	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
1451 	u32        r32;
1452 
1453 	/**
1454 	 * For crossbow, port id is same as pci function.
1455 	 */
1456 	if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT) {
1457 		ioc->port_id = bfa_ioc_pcifn(ioc);
1458 		return;
1459 	}
1460 
1461 	/**
1462 	 * For catapult, base port id on personality register and IOC type
1463 	 */
1464 	r32 = bfa_reg_read(rb + FNC_PERS_REG);
1465 	r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc));
1466 	ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH;
1467 
1468 	bfa_trc(ioc, bfa_ioc_pcifn(ioc));
1469 	bfa_trc(ioc, ioc->port_id);
1470 }
1471 
1472 
1473 
1474 /**
1475  *  bfa_ioc_public
1476  */
1477 
1478 /**
1479 * Set interrupt mode for a function: INTX or MSIX
1480  */
1481 void
1482 bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix)
1483 {
1484 	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
1485 	u32        r32, mode;
1486 
1487 	r32 = bfa_reg_read(rb + FNC_PERS_REG);
1488 	bfa_trc(ioc, r32);
1489 
1490 	mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) &
1491 		__F0_INTX_STATUS;
1492 
1493 	/**
1494 	 * If already in desired mode, do not change anything
1495 	 */
1496 	if (!msix && mode)
1497 		return;
1498 
1499 	if (msix)
1500 		mode = __F0_INTX_STATUS_MSIX;
1501 	else
1502 		mode = __F0_INTX_STATUS_INTA;
1503 
1504 	r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
1505 	r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)));
1506 	bfa_trc(ioc, r32);
1507 
1508 	bfa_reg_write(rb + FNC_PERS_REG, r32);
1509 }
1510 
1511 bfa_status_t
1512 bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1513 {
1514 	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
1515 	u32        pll_sclk, pll_fclk, r32;
1516 
1517 	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
1518 		pll_sclk =
1519 			__APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN |
1520 			__APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(0U) |
1521 			__APP_PLL_312_JITLMT0_1(3U) |
1522 			__APP_PLL_312_CNTLMT0_1(1U);
1523 		pll_fclk =
1524 			__APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN |
1525 			__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(0U) |
1526 			__APP_PLL_425_JITLMT0_1(3U) |
1527 			__APP_PLL_425_CNTLMT0_1(1U);
1528 
1529 		/**
1530 		 * 	For catapult, choose operational mode FC/FCoE
1531 		 */
1532 		if (ioc->fcmode) {
1533 			bfa_reg_write((rb + OP_MODE), 0);
1534 			bfa_reg_write((rb + ETH_MAC_SER_REG),
1535 				      __APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2
1536 				      | __APP_EMS_CHANNEL_SEL);
1537 		} else {
1538 			ioc->pllinit = BFA_TRUE;
1539 			bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE);
1540 			bfa_reg_write((rb + ETH_MAC_SER_REG),
1541 				      __APP_EMS_REFCKBUFEN1);
1542 		}
1543 	} else {
1544 		pll_sclk =
1545 			__APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN |
1546 			__APP_PLL_312_P0_1(3U) | __APP_PLL_312_JITLMT0_1(3U) |
1547 			__APP_PLL_312_CNTLMT0_1(3U);
1548 		pll_fclk =
1549 			__APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN |
1550 			__APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) |
1551 			__APP_PLL_425_JITLMT0_1(3U) |
1552 			__APP_PLL_425_CNTLMT0_1(3U);
1553 	}
1554 
1555 	bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT);
1556 	bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT);
1557 
1558 	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
1559 	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
1560 	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
1561 	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
1562 	bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU);
1563 	bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU);
1564 
1565 	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
1566 		      __APP_PLL_312_LOGIC_SOFT_RESET);
1567 	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
1568 		      __APP_PLL_312_BYPASS | __APP_PLL_312_LOGIC_SOFT_RESET);
1569 	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
1570 		      __APP_PLL_425_LOGIC_SOFT_RESET);
1571 	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
1572 		      __APP_PLL_425_BYPASS | __APP_PLL_425_LOGIC_SOFT_RESET);
1573 	bfa_os_udelay(2);
1574 	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
1575 		      __APP_PLL_312_LOGIC_SOFT_RESET);
1576 	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
1577 		      __APP_PLL_425_LOGIC_SOFT_RESET);
1578 
1579 	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg,
1580 		      pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET);
1581 	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg,
1582 		      pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET);
1583 
1584 	/**
1585 	 * Wait for PLLs to lock.
1586 	 */
1587 	bfa_os_udelay(2000);
1588 	bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU);
1589 	bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU);
1590 
1591 	bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk);
1592 	bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk);
1593 
1594 	if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) {
1595 		bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START);
1596 		bfa_os_udelay(1000);
1597 		r32 = bfa_reg_read((rb + MBIST_STAT_REG));
1598 		bfa_trc(ioc, r32);
1599 	}
1600 
1601 	return BFA_STATUS_OK;
1602 }
1603 
1604 /**
1605  * Interface used by diag module to do firmware boot with memory test
1606  * as the entry vector.
1607  */
1608 void
1609 bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param)
1610 {
1611 	bfa_os_addr_t   rb;
1612 
1613 	bfa_ioc_stats(ioc, ioc_boots);
1614 
1615 	if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1616 		return;
1617 
1618 	/**
1619 	 * Initialize IOC state of all functions on a chip reset.
1620 	 */
1621 	rb = ioc->pcidev.pci_bar_kva;
1622 	if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
1623 		bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST);
1624 		bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST);
1625 	} else {
1626 		bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_INITING);
1627 		bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_INITING);
1628 	}
1629 
1630 	bfa_ioc_download_fw(ioc, boot_type, boot_param);
1631 
1632 	/**
1633 	 * Enable interrupts just before starting LPU
1634 	 */
1635 	ioc->cbfn->reset_cbfn(ioc->bfa);
1636 	bfa_ioc_lpu_start(ioc);
1637 }
1638 
1639 /**
1640  * Enable/disable IOC failure auto recovery.
1641  */
1642 void
1643 bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
1644 {
1645 	bfa_auto_recover = BFA_FALSE;
1646 }
1647 
1648 
1649 bfa_boolean_t
1650 bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
1651 {
1652 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
1653 }
1654 
1655 void
1656 bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
1657 {
1658 	u32       *msgp = mbmsg;
1659 	u32        r32;
1660 	int             i;
1661 
1662 	/**
1663 	 * read the MBOX msg
1664 	 */
1665 	for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
1666 	     i++) {
1667 		r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox +
1668 				   i * sizeof(u32));
1669 		msgp[i] = bfa_os_htonl(r32);
1670 	}
1671 
1672 	/**
1673 	 * turn off mailbox interrupt by clearing mailbox status
1674 	 */
1675 	bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1);
1676 	bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd);
1677 }
1678 
1679 void
1680 bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
1681 {
1682 	union bfi_ioc_i2h_msg_u *msg;
1683 
1684 	msg = (union bfi_ioc_i2h_msg_u *)m;
1685 
1686 	bfa_ioc_stats(ioc, ioc_isrs);
1687 
1688 	switch (msg->mh.msg_id) {
1689 	case BFI_IOC_I2H_HBEAT:
1690 		break;
1691 
1692 	case BFI_IOC_I2H_READY_EVENT:
1693 		bfa_fsm_send_event(ioc, IOC_E_FWREADY);
1694 		break;
1695 
1696 	case BFI_IOC_I2H_ENABLE_REPLY:
1697 		bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
1698 		break;
1699 
1700 	case BFI_IOC_I2H_DISABLE_REPLY:
1701 		bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
1702 		break;
1703 
1704 	case BFI_IOC_I2H_GETATTR_REPLY:
1705 		bfa_ioc_getattr_reply(ioc);
1706 		break;
1707 
1708 	default:
1709 		bfa_trc(ioc, msg->mh.msg_id);
1710 		bfa_assert(0);
1711 	}
1712 }
1713 
1714 /**
1715  * IOC attach time initialization and setup.
1716  *
1717  * @param[in]	ioc	memory for IOC
1718  * @param[in]	bfa	driver instance structure
1719  * @param[in]	trcmod	kernel trace module
1720  * @param[in]	aen	kernel aen event module
1721  * @param[in]	logm	kernel logging module
1722  */
1723 void
1724 bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
1725 	       struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod,
1726 	       struct bfa_aen_s *aen, struct bfa_log_mod_s *logm)
1727 {
1728 	ioc->bfa = bfa;
1729 	ioc->cbfn = cbfn;
1730 	ioc->timer_mod = timer_mod;
1731 	ioc->trcmod = trcmod;
1732 	ioc->aen = aen;
1733 	ioc->logm = logm;
1734 	ioc->fcmode = BFA_FALSE;
1735 	ioc->pllinit = BFA_FALSE;
1736 	ioc->dbg_fwsave_once = BFA_TRUE;
1737 
1738 	bfa_ioc_mbox_attach(ioc);
1739 	INIT_LIST_HEAD(&ioc->hb_notify_q);
1740 
1741 	bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
1742 }
1743 
1744 /**
1745  * Driver detach time IOC cleanup.
1746  */
1747 void
1748 bfa_ioc_detach(struct bfa_ioc_s *ioc)
1749 {
1750 	bfa_fsm_send_event(ioc, IOC_E_DETACH);
1751 }
1752 
1753 /**
1754  * Setup IOC PCI properties.
1755  *
1756  * @param[in]	pcidev	PCI device information for this IOC
1757  */
1758 void
1759 bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
1760 		 enum bfi_mclass mc)
1761 {
1762 	ioc->ioc_mc = mc;
1763 	ioc->pcidev = *pcidev;
1764 	ioc->ctdev = (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT);
1765 	ioc->cna = ioc->ctdev && !ioc->fcmode;
1766 
1767 	bfa_ioc_map_port(ioc);
1768 	bfa_ioc_reg_init(ioc);
1769 }
1770 
1771 /**
1772  * Initialize IOC dma memory
1773  *
1774  * @param[in]	dm_kva	kernel virtual address of IOC dma memory
1775  * @param[in]	dm_pa	physical address of IOC dma memory
1776  */
1777 void
1778 bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
1779 {
1780 	/**
1781 	 * dma memory for firmware attribute
1782 	 */
1783 	ioc->attr_dma.kva = dm_kva;
1784 	ioc->attr_dma.pa = dm_pa;
1785 	ioc->attr = (struct bfi_ioc_attr_s *)dm_kva;
1786 }
1787 
1788 /**
1789  * Return size of dma memory required.
1790  */
1791 u32
1792 bfa_ioc_meminfo(void)
1793 {
1794 	return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
1795 }
1796 
1797 void
1798 bfa_ioc_enable(struct bfa_ioc_s *ioc)
1799 {
1800 	bfa_ioc_stats(ioc, ioc_enables);
1801 	ioc->dbg_fwsave_once = BFA_TRUE;
1802 
1803 	bfa_fsm_send_event(ioc, IOC_E_ENABLE);
1804 }
1805 
1806 void
1807 bfa_ioc_disable(struct bfa_ioc_s *ioc)
1808 {
1809 	bfa_ioc_stats(ioc, ioc_disables);
1810 	bfa_fsm_send_event(ioc, IOC_E_DISABLE);
1811 }
1812 
1813 /**
1814  * Returns memory required for saving firmware trace in case of crash.
1815  * Driver must call this interface to allocate memory required for
1816  * automatic saving of firmware trace. Driver should call
1817  * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this
1818  * trace memory.
1819  */
1820 int
1821 bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
1822 {
1823 return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
1824 }
1825 
1826 /**
1827  * Initialize memory for saving firmware trace. Driver must initialize
1828  * trace memory before call bfa_ioc_enable().
1829  */
1830 void
1831 bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
1832 {
1833 	bfa_assert(ioc->auto_recover);
1834 	ioc->dbg_fwsave = dbg_fwsave;
1835 	ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover);
1836 }
1837 
1838 u32
1839 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr)
1840 {
1841 	return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
1842 }
1843 
1844 u32
1845 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
1846 {
1847 	return PSS_SMEM_PGOFF(fmaddr);
1848 }
1849 
1850 /**
1851  * Register mailbox message handler functions
1852  *
1853  * @param[in]	ioc		IOC instance
1854  * @param[in]	mcfuncs		message class handler functions
1855  */
1856 void
1857 bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
1858 {
1859 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1860 	int             mc;
1861 
1862 	for (mc = 0; mc < BFI_MC_MAX; mc++)
1863 		mod->mbhdlr[mc].cbfn = mcfuncs[mc];
1864 }
1865 
1866 /**
1867  * Register mailbox message handler function, to be called by common modules
1868  */
1869 void
1870 bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
1871 		    bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
1872 {
1873 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1874 
1875 	mod->mbhdlr[mc].cbfn = cbfn;
1876 	mod->mbhdlr[mc].cbarg = cbarg;
1877 }
1878 
1879 /**
1880  * Queue a mailbox command request to firmware. Waits if mailbox is busy.
1881  * Responsibility of caller to serialize
1882  *
1883  * @param[in]	ioc	IOC instance
1884  * @param[i]	cmd	Mailbox command
1885  */
1886 void
1887 bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
1888 {
1889 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1890 	u32        stat;
1891 
1892 	/**
1893 	 * If a previous command is pending, queue new command
1894 	 */
1895 	if (!list_empty(&mod->cmd_q)) {
1896 		list_add_tail(&cmd->qe, &mod->cmd_q);
1897 		return;
1898 	}
1899 
1900 	/**
1901 	 * If mailbox is busy, queue command for poll timer
1902 	 */
1903 	stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd);
1904 	if (stat) {
1905 		list_add_tail(&cmd->qe, &mod->cmd_q);
1906 		return;
1907 	}
1908 
1909 	/**
1910 	 * mailbox is free -- queue command to firmware
1911 	 */
1912 	bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1913 }
1914 
1915 /**
1916  * Handle mailbox interrupts
1917  */
1918 void
1919 bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
1920 {
1921 	struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1922 	struct bfi_mbmsg_s m;
1923 	int             mc;
1924 
1925 	bfa_ioc_msgget(ioc, &m);
1926 
1927 	/**
1928 	 * Treat IOC message class as special.
1929 	 */
1930 	mc = m.mh.msg_class;
1931 	if (mc == BFI_MC_IOC) {
1932 		bfa_ioc_isr(ioc, &m);
1933 		return;
1934 	}
1935 
1936 	if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
1937 		return;
1938 
1939 	mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
1940 }
1941 
1942 void
1943 bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
1944 {
1945 	bfa_fsm_send_event(ioc, IOC_E_HWERROR);
1946 }
1947 
1948 #ifndef BFA_BIOS_BUILD
1949 
1950 /**
1951  * return true if IOC is disabled
1952  */
1953 bfa_boolean_t
1954 bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
1955 {
1956 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling)
1957 		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
1958 }
1959 
1960 /**
1961  * return true if IOC firmware is different.
1962  */
1963 bfa_boolean_t
1964 bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
1965 {
1966 	return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset)
1967 		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck)
1968 		|| bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
1969 }
1970 
1971 #define bfa_ioc_state_disabled(__sm)		\
1972 	(((__sm) == BFI_IOC_UNINIT) ||		\
1973 	 ((__sm) == BFI_IOC_INITING) ||		\
1974 	 ((__sm) == BFI_IOC_HWINIT) ||		\
1975 	 ((__sm) == BFI_IOC_DISABLED) ||	\
1976 	 ((__sm) == BFI_IOC_HBFAIL) ||		\
1977 	 ((__sm) == BFI_IOC_CFG_DISABLED))
1978 
1979 /**
1980  * Check if adapter is disabled -- both IOCs should be in a disabled
1981  * state.
1982  */
1983 bfa_boolean_t
1984 bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
1985 {
1986 	u32        ioc_state;
1987 	bfa_os_addr_t   rb = ioc->pcidev.pci_bar_kva;
1988 
1989 	if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
1990 		return BFA_FALSE;
1991 
1992 	ioc_state = bfa_reg_read(rb + BFA_IOC0_STATE_REG);
1993 	if (!bfa_ioc_state_disabled(ioc_state))
1994 		return BFA_FALSE;
1995 
1996 	ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG);
1997 	if (!bfa_ioc_state_disabled(ioc_state))
1998 		return BFA_FALSE;
1999 
2000 	return BFA_TRUE;
2001 }
2002 
2003 /**
2004  * Add to IOC heartbeat failure notification queue. To be used by common
2005  * modules such as
2006  */
2007 void
2008 bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
2009 			struct bfa_ioc_hbfail_notify_s *notify)
2010 {
2011 	list_add_tail(&notify->qe, &ioc->hb_notify_q);
2012 }
2013 
2014 #define BFA_MFG_NAME "Brocade"
2015 void
2016 bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2017 			 struct bfa_adapter_attr_s *ad_attr)
2018 {
2019 	struct bfi_ioc_attr_s *ioc_attr;
2020 	char            model[BFA_ADAPTER_MODEL_NAME_LEN];
2021 
2022 	ioc_attr = ioc->attr;
2023 	bfa_os_memcpy((void *)&ad_attr->serial_num,
2024 		      (void *)ioc_attr->brcd_serialnum,
2025 		      BFA_ADAPTER_SERIAL_NUM_LEN);
2026 
2027 	bfa_os_memcpy(&ad_attr->fw_ver, ioc_attr->fw_version, BFA_VERSION_LEN);
2028 	bfa_os_memcpy(&ad_attr->optrom_ver, ioc_attr->optrom_version,
2029 		      BFA_VERSION_LEN);
2030 	bfa_os_memcpy(&ad_attr->manufacturer, BFA_MFG_NAME,
2031 		      BFA_ADAPTER_MFG_NAME_LEN);
2032 	bfa_os_memcpy(&ad_attr->vpd, &ioc_attr->vpd,
2033 		      sizeof(struct bfa_mfg_vpd_s));
2034 
2035 	ad_attr->nports = BFI_ADAPTER_GETP(NPORTS, ioc_attr->adapter_prop);
2036 	ad_attr->max_speed = BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop);
2037 
2038 	/**
2039 	 * model name
2040 	 */
2041 	if (BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop) == 10) {
2042 		strcpy(model, "BR-10?0");
2043 		model[5] = '0' + ad_attr->nports;
2044 	} else {
2045 		strcpy(model, "Brocade-??5");
2046 		model[8] =
2047 			'0' + BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop);
2048 		model[9] = '0' + ad_attr->nports;
2049 	}
2050 
2051 	if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2052 		ad_attr->prototype = 1;
2053 	else
2054 		ad_attr->prototype = 0;
2055 
2056 	bfa_os_memcpy(&ad_attr->model, model, BFA_ADAPTER_MODEL_NAME_LEN);
2057 	bfa_os_memcpy(&ad_attr->model_descr, &ad_attr->model,
2058 		      BFA_ADAPTER_MODEL_NAME_LEN);
2059 
2060 	ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
2061 	ad_attr->mac = bfa_ioc_get_mac(ioc);
2062 
2063 	ad_attr->pcie_gen = ioc_attr->pcie_gen;
2064 	ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2065 	ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2066 	ad_attr->asic_rev = ioc_attr->asic_rev;
2067 	ad_attr->hw_ver[0] = 'R';
2068 	ad_attr->hw_ver[1] = 'e';
2069 	ad_attr->hw_ver[2] = 'v';
2070 	ad_attr->hw_ver[3] = '-';
2071 	ad_attr->hw_ver[4] = ioc_attr->asic_rev;
2072 	ad_attr->hw_ver[5] = '\0';
2073 
2074 	ad_attr->cna_capable = ioc->cna;
2075 }
2076 
2077 void
2078 bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2079 {
2080 	bfa_os_memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
2081 
2082 	ioc_attr->state = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2083 	ioc_attr->port_id = ioc->port_id;
2084 
2085 	if (!ioc->ctdev)
2086 		ioc_attr->ioc_type = BFA_IOC_TYPE_FC;
2087 	else if (ioc->ioc_mc == BFI_MC_IOCFC)
2088 		ioc_attr->ioc_type = BFA_IOC_TYPE_FCoE;
2089 	else if (ioc->ioc_mc == BFI_MC_LL)
2090 		ioc_attr->ioc_type = BFA_IOC_TYPE_LL;
2091 
2092 	bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2093 
2094 	ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2095 	ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
2096 	ioc_attr->pci_attr.chip_rev[0] = 'R';
2097 	ioc_attr->pci_attr.chip_rev[1] = 'e';
2098 	ioc_attr->pci_attr.chip_rev[2] = 'v';
2099 	ioc_attr->pci_attr.chip_rev[3] = '-';
2100 	ioc_attr->pci_attr.chip_rev[4] = ioc_attr->adapter_attr.asic_rev;
2101 	ioc_attr->pci_attr.chip_rev[5] = '\0';
2102 }
2103 
2104 /**
2105  *  hal_wwn_public
2106  */
2107 wwn_t
2108 bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
2109 {
2110 	union {
2111 		wwn_t           wwn;
2112 		u8         byte[sizeof(wwn_t)];
2113 	}
2114 	w;
2115 
2116 	w.wwn = ioc->attr->mfg_wwn;
2117 
2118 	if (bfa_ioc_portid(ioc) == 1)
2119 		w.byte[7]++;
2120 
2121 	return w.wwn;
2122 }
2123 
2124 wwn_t
2125 bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc)
2126 {
2127 	union {
2128 		wwn_t           wwn;
2129 		u8         byte[sizeof(wwn_t)];
2130 	}
2131 	w;
2132 
2133 	w.wwn = ioc->attr->mfg_wwn;
2134 
2135 	if (bfa_ioc_portid(ioc) == 1)
2136 		w.byte[7]++;
2137 
2138 	w.byte[0] = 0x20;
2139 
2140 	return w.wwn;
2141 }
2142 
2143 wwn_t
2144 bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst)
2145 {
2146 	union {
2147 		wwn_t           wwn;
2148 		u8         byte[sizeof(wwn_t)];
2149 	}
2150 	w              , w5;
2151 
2152 	bfa_trc(ioc, inst);
2153 
2154 	w.wwn = ioc->attr->mfg_wwn;
2155 	w5.byte[0] = 0x50 | w.byte[2] >> 4;
2156 	w5.byte[1] = w.byte[2] << 4 | w.byte[3] >> 4;
2157 	w5.byte[2] = w.byte[3] << 4 | w.byte[4] >> 4;
2158 	w5.byte[3] = w.byte[4] << 4 | w.byte[5] >> 4;
2159 	w5.byte[4] = w.byte[5] << 4 | w.byte[6] >> 4;
2160 	w5.byte[5] = w.byte[6] << 4 | w.byte[7] >> 4;
2161 	w5.byte[6] = w.byte[7] << 4 | (inst & 0x0f00) >> 8;
2162 	w5.byte[7] = (inst & 0xff);
2163 
2164 	return w5.wwn;
2165 }
2166 
2167 u64
2168 bfa_ioc_get_adid(struct bfa_ioc_s *ioc)
2169 {
2170 	return ioc->attr->mfg_wwn;
2171 }
2172 
2173 mac_t
2174 bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2175 {
2176 	mac_t           mac;
2177 
2178 	mac = ioc->attr->mfg_mac;
2179 	mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2180 
2181 	return mac;
2182 }
2183 
2184 void
2185 bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
2186 {
2187 	ioc->fcmode = BFA_TRUE;
2188 	ioc->port_id = bfa_ioc_pcifn(ioc);
2189 }
2190 
2191 bfa_boolean_t
2192 bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
2193 {
2194 	return ioc->fcmode || (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT);
2195 }
2196 
2197 /**
2198  * Return true if interrupt should be claimed.
2199  */
2200 bfa_boolean_t
2201 bfa_ioc_intx_claim(struct bfa_ioc_s *ioc)
2202 {
2203 	u32        isr, msk;
2204 
2205 	/**
2206 	 * Always claim if not catapult.
2207 	 */
2208 	if (!ioc->ctdev)
2209 		return BFA_TRUE;
2210 
2211 	/**
2212 	 * FALSE if next device is claiming interrupt.
2213 	 * TRUE if next device is not interrupting or not present.
2214 	 */
2215 	msk = bfa_reg_read(ioc->ioc_regs.shirq_msk_next);
2216 	isr = bfa_reg_read(ioc->ioc_regs.shirq_isr_next);
2217 	return !(isr & ~msk);
2218 }
2219 
2220 /**
2221  * Send AEN notification
2222  */
2223 static void
2224 bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
2225 {
2226 	union bfa_aen_data_u aen_data;
2227 	struct bfa_log_mod_s *logmod = ioc->logm;
2228 	s32         inst_num = 0;
2229 	struct bfa_ioc_attr_s ioc_attr;
2230 
2231 	switch (event) {
2232 	case BFA_IOC_AEN_HBGOOD:
2233 		bfa_log(logmod, BFA_AEN_IOC_HBGOOD, inst_num);
2234 		break;
2235 	case BFA_IOC_AEN_HBFAIL:
2236 		bfa_log(logmod, BFA_AEN_IOC_HBFAIL, inst_num);
2237 		break;
2238 	case BFA_IOC_AEN_ENABLE:
2239 		bfa_log(logmod, BFA_AEN_IOC_ENABLE, inst_num);
2240 		break;
2241 	case BFA_IOC_AEN_DISABLE:
2242 		bfa_log(logmod, BFA_AEN_IOC_DISABLE, inst_num);
2243 		break;
2244 	case BFA_IOC_AEN_FWMISMATCH:
2245 		bfa_log(logmod, BFA_AEN_IOC_FWMISMATCH, inst_num);
2246 		break;
2247 	default:
2248 		break;
2249 	}
2250 
2251 	memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn));
2252 	memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac));
2253 	bfa_ioc_get_attr(ioc, &ioc_attr);
2254 	switch (ioc_attr.ioc_type) {
2255 	case BFA_IOC_TYPE_FC:
2256 		aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
2257 		break;
2258 	case BFA_IOC_TYPE_FCoE:
2259 		aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc);
2260 		aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
2261 		break;
2262 	case BFA_IOC_TYPE_LL:
2263 		aen_data.ioc.mac = bfa_ioc_get_mac(ioc);
2264 		break;
2265 	default:
2266 		bfa_assert(ioc_attr.ioc_type == BFA_IOC_TYPE_FC);
2267 		break;
2268 	}
2269 	aen_data.ioc.ioc_type = ioc_attr.ioc_type;
2270 }
2271 
2272 /**
2273  * Retrieve saved firmware trace from a prior IOC failure.
2274  */
2275 bfa_status_t
2276 bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2277 {
2278 	int             tlen;
2279 
2280 	if (ioc->dbg_fwsave_len == 0)
2281 		return BFA_STATUS_ENOFSAVE;
2282 
2283 	tlen = *trclen;
2284 	if (tlen > ioc->dbg_fwsave_len)
2285 		tlen = ioc->dbg_fwsave_len;
2286 
2287 	bfa_os_memcpy(trcdata, ioc->dbg_fwsave, tlen);
2288 	*trclen = tlen;
2289 	return BFA_STATUS_OK;
2290 }
2291 
2292 /**
2293  * Retrieve saved firmware trace from a prior IOC failure.
2294  */
2295 bfa_status_t
2296 bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2297 {
2298 	u32        pgnum;
2299 	u32        loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2300 	int             i, tlen;
2301 	u32       *tbuf = trcdata, r32;
2302 
2303 	bfa_trc(ioc, *trclen);
2304 
2305 	pgnum = bfa_ioc_smem_pgnum(ioc, loff);
2306 	loff = bfa_ioc_smem_pgoff(ioc, loff);
2307 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
2308 
2309 	tlen = *trclen;
2310 	if (tlen > BFA_DBG_FWTRC_LEN)
2311 		tlen = BFA_DBG_FWTRC_LEN;
2312 	tlen /= sizeof(u32);
2313 
2314 	bfa_trc(ioc, tlen);
2315 
2316 	for (i = 0; i < tlen; i++) {
2317 		r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
2318 		tbuf[i] = bfa_os_ntohl(r32);
2319 		loff += sizeof(u32);
2320 
2321 		/**
2322 		 * handle page offset wrap around
2323 		 */
2324 		loff = PSS_SMEM_PGOFF(loff);
2325 		if (loff == 0) {
2326 			pgnum++;
2327 			bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum);
2328 		}
2329 	}
2330 	bfa_reg_write(ioc->ioc_regs.host_page_num_fn,
2331 		      bfa_ioc_smem_pgnum(ioc, 0));
2332 	bfa_trc(ioc, pgnum);
2333 
2334 	*trclen = tlen * sizeof(u32);
2335 	return BFA_STATUS_OK;
2336 }
2337 
2338 /**
2339  * Save firmware trace if configured.
2340  */
2341 static void
2342 bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
2343 {
2344 	int             tlen;
2345 
2346 	if (ioc->dbg_fwsave_len) {
2347 		tlen = ioc->dbg_fwsave_len;
2348 		bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2349 	}
2350 }
2351 
2352 /**
2353  * Firmware failure detected. Start recovery actions.
2354  */
2355 static void
2356 bfa_ioc_recover(struct bfa_ioc_s *ioc)
2357 {
2358 	if (ioc->dbg_fwsave_once) {
2359 		ioc->dbg_fwsave_once = BFA_FALSE;
2360 		bfa_ioc_debug_save(ioc);
2361 	}
2362 
2363 	bfa_ioc_stats(ioc, ioc_hbfails);
2364 	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2365 }
2366 
2367 #else
2368 
2369 static void
2370 bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event)
2371 {
2372 }
2373 
2374 static void
2375 bfa_ioc_recover(struct bfa_ioc_s *ioc)
2376 {
2377 	bfa_assert(0);
2378 }
2379 
2380 #endif
2381 
2382 
2383