blob: 9173bf20ffbad176ca67c3c6369e7081c2d27050 [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Jing Huang7725ccf2009-09-23 17:46:15 -07003 * 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
Maggie Zhangf16a1752010-12-09 19:12:32 -080018#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070019#include "bfa_ioc.h"
20#include "bfi_ctreg.h"
21#include "bfa_defs.h"
22#include "bfa_defs_svc.h"
Jing Huang7725ccf2009-09-23 17:46:15 -070023
Krishna Gudipati7af074d2010-03-05 19:35:45 -080024BFA_TRC_FILE(CNA, IOC);
Jing Huang7725ccf2009-09-23 17:46:15 -070025
Jing Huang5fbe25c2010-10-18 17:17:23 -070026/*
Jing Huang7725ccf2009-09-23 17:46:15 -070027 * IOC local definitions
28 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070029#define BFA_IOC_TOV 3000 /* msecs */
30#define BFA_IOC_HWSEM_TOV 500 /* msecs */
31#define BFA_IOC_HB_TOV 500 /* msecs */
32#define BFA_IOC_HWINIT_MAX 2
33#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
Jing Huang7725ccf2009-09-23 17:46:15 -070034
35#define bfa_ioc_timer_start(__ioc) \
36 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
37 bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
38#define bfa_ioc_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
39
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070040#define bfa_hb_timer_start(__ioc) \
41 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer, \
42 bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
43#define bfa_hb_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->hb_timer)
44
Jing Huang7725ccf2009-09-23 17:46:15 -070045#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
Jing Huang7725ccf2009-09-23 17:46:15 -070046
Jing Huang5fbe25c2010-10-18 17:17:23 -070047/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080048 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
49 */
50
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070051#define bfa_ioc_firmware_lock(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080052 ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070053#define bfa_ioc_firmware_unlock(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080054 ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
Krishna Gudipati0a20de42010-03-05 19:34:20 -080055#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
56#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070057#define bfa_ioc_notify_hbfail(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080058 ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
59
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070060#ifdef BFA_IOC_IS_UEFI
61#define bfa_ioc_is_bios_optrom(__ioc) (0)
62#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
63#else
64#define bfa_ioc_is_bios_optrom(__ioc) \
65 (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
66#define bfa_ioc_is_uefi(__ioc) (0)
67#endif
68
69#define bfa_ioc_mbox_cmd_pending(__ioc) \
70 (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
Jing Huang53440262010-10-18 17:12:29 -070071 readl((__ioc)->ioc_regs.hfn_mbox_cmd))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070072
73bfa_boolean_t bfa_auto_recover = BFA_TRUE;
Jing Huang7725ccf2009-09-23 17:46:15 -070074
75/*
76 * forward declarations
77 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070078static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070079static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
80static void bfa_ioc_timeout(void *ioc);
81static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
82static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
83static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
84static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070085static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
86static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
87static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
88static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
89static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
90static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -080091static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
92static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070093static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -070094
Jing Huang7725ccf2009-09-23 17:46:15 -070095
Jing Huang5fbe25c2010-10-18 17:17:23 -070096/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070097 * IOC state machine definitions/declarations
Jing Huang7725ccf2009-09-23 17:46:15 -070098 */
99enum ioc_event {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700100 IOC_E_RESET = 1, /* IOC reset request */
101 IOC_E_ENABLE = 2, /* IOC enable request */
102 IOC_E_DISABLE = 3, /* IOC disable request */
103 IOC_E_DETACH = 4, /* driver detach cleanup */
104 IOC_E_ENABLED = 5, /* f/w enabled */
105 IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
106 IOC_E_DISABLED = 7, /* f/w disabled */
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800107 IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700108 IOC_E_HBFAIL = 9, /* heartbeat failure */
109 IOC_E_HWERROR = 10, /* hardware error interrupt */
110 IOC_E_TIMEOUT = 11, /* timeout */
Jing Huang7725ccf2009-09-23 17:46:15 -0700111};
112
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700113bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700114bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700115bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
116bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
117bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800118bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700119bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700120bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
121bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
122
123static struct bfa_sm_table_s ioc_sm_table[] = {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700124 {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
Jing Huang7725ccf2009-09-23 17:46:15 -0700125 {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700126 {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
Jing Huang7725ccf2009-09-23 17:46:15 -0700127 {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
128 {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800129 {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700130 {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
Jing Huang7725ccf2009-09-23 17:46:15 -0700131 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
132 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
133};
134
Jing Huang5fbe25c2010-10-18 17:17:23 -0700135/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700136 * IOCPF state machine definitions/declarations
137 */
138
139#define bfa_iocpf_timer_start(__ioc) \
140 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
141 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
142#define bfa_iocpf_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
143
144#define bfa_iocpf_recovery_timer_start(__ioc) \
145 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
146 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
147
148#define bfa_sem_timer_start(__ioc) \
149 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer, \
150 bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
151#define bfa_sem_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->sem_timer)
152
153/*
154 * Forward declareations for iocpf state machine
155 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700156static void bfa_iocpf_timeout(void *ioc_arg);
157static void bfa_iocpf_sem_timeout(void *ioc_arg);
158
Jing Huang5fbe25c2010-10-18 17:17:23 -0700159/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700160 * IOCPF state machine events
161 */
162enum iocpf_event {
163 IOCPF_E_ENABLE = 1, /* IOCPF enable request */
164 IOCPF_E_DISABLE = 2, /* IOCPF disable request */
165 IOCPF_E_STOP = 3, /* stop on driver detach */
166 IOCPF_E_FWREADY = 4, /* f/w initialization done */
167 IOCPF_E_FWRSP_ENABLE = 5, /* enable f/w response */
168 IOCPF_E_FWRSP_DISABLE = 6, /* disable f/w response */
169 IOCPF_E_FAIL = 7, /* failure notice by ioc sm */
170 IOCPF_E_INITFAIL = 8, /* init fail notice by ioc sm */
171 IOCPF_E_GETATTRFAIL = 9, /* init fail notice by ioc sm */
172 IOCPF_E_SEMLOCKED = 10, /* h/w semaphore is locked */
173 IOCPF_E_TIMEOUT = 11, /* f/w response timeout */
174};
175
Jing Huang5fbe25c2010-10-18 17:17:23 -0700176/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700177 * IOCPF states
178 */
179enum bfa_iocpf_state {
180 BFA_IOCPF_RESET = 1, /* IOC is in reset state */
181 BFA_IOCPF_SEMWAIT = 2, /* Waiting for IOC h/w semaphore */
182 BFA_IOCPF_HWINIT = 3, /* IOC h/w is being initialized */
183 BFA_IOCPF_READY = 4, /* IOCPF is initialized */
184 BFA_IOCPF_INITFAIL = 5, /* IOCPF failed */
185 BFA_IOCPF_FAIL = 6, /* IOCPF failed */
186 BFA_IOCPF_DISABLING = 7, /* IOCPF is being disabled */
187 BFA_IOCPF_DISABLED = 8, /* IOCPF is disabled */
188 BFA_IOCPF_FWMISMATCH = 9, /* IOC f/w different from drivers */
189};
190
191bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
192bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
193bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
194bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
195bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
196bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
197bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
198bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
199bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
200bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
201bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
202
203static struct bfa_sm_table_s iocpf_sm_table[] = {
204 {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
205 {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
206 {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
207 {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
208 {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
209 {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
210 {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
211 {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
212 {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
213 {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
214 {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
215};
216
Jing Huang5fbe25c2010-10-18 17:17:23 -0700217/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700218 * IOC State Machine
219 */
220
Jing Huang5fbe25c2010-10-18 17:17:23 -0700221/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700222 * Beginning state. IOC uninit state.
223 */
224
225static void
226bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
227{
228}
229
Jing Huang5fbe25c2010-10-18 17:17:23 -0700230/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700231 * IOC is in uninit state.
232 */
233static void
234bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
235{
236 bfa_trc(ioc, event);
237
238 switch (event) {
239 case IOC_E_RESET:
240 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
241 break;
242
243 default:
244 bfa_sm_fault(ioc, event);
245 }
246}
Jing Huang5fbe25c2010-10-18 17:17:23 -0700247/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700248 * Reset entry actions -- initialize state machine
249 */
250static void
251bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
252{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700253 bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
Jing Huang7725ccf2009-09-23 17:46:15 -0700254}
255
Jing Huang5fbe25c2010-10-18 17:17:23 -0700256/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700257 * IOC is in reset state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700258 */
259static void
260bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
261{
262 bfa_trc(ioc, event);
263
264 switch (event) {
265 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700266 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
267 break;
268
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700269 case IOC_E_DISABLE:
270 bfa_ioc_disable_comp(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700271 break;
272
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700273 case IOC_E_DETACH:
274 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700275 break;
276
277 default:
278 bfa_sm_fault(ioc, event);
279 }
280}
281
282
283static void
284bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
285{
Maggie Zhangf7f73812010-12-09 19:08:43 -0800286 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700287}
288
Jing Huang5fbe25c2010-10-18 17:17:23 -0700289/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700290 * Host IOC function is being enabled, awaiting response from firmware.
291 * Semaphore is acquired.
292 */
293static void
294bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
295{
296 bfa_trc(ioc, event);
297
298 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700299 case IOC_E_ENABLED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700300 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
301 break;
302
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800303 case IOC_E_PFFAILED:
304 /* !!! fall through !!! */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700305 case IOC_E_HWERROR:
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800306 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
307 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
308 if (event != IOC_E_PFFAILED)
309 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700310 break;
311
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700312 case IOC_E_DISABLE:
313 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
314 break;
315
316 case IOC_E_DETACH:
317 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800318 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700319 break;
320
321 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700322 break;
323
324 default:
325 bfa_sm_fault(ioc, event);
326 }
327}
328
329
330static void
331bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
332{
333 bfa_ioc_timer_start(ioc);
334 bfa_ioc_send_getattr(ioc);
335}
336
Jing Huang5fbe25c2010-10-18 17:17:23 -0700337/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700338 * IOC configuration in progress. Timer is active.
339 */
340static void
341bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
342{
343 bfa_trc(ioc, event);
344
345 switch (event) {
346 case IOC_E_FWRSP_GETATTR:
347 bfa_ioc_timer_stop(ioc);
Jing Huang07b28382010-07-08 19:59:24 -0700348 bfa_ioc_check_attr_wwns(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700349 bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
350 break;
351
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700352 break;
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800353 case IOC_E_PFFAILED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700354 case IOC_E_HWERROR:
355 bfa_ioc_timer_stop(ioc);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800356 /* !!! fall through !!! */
Jing Huang7725ccf2009-09-23 17:46:15 -0700357 case IOC_E_TIMEOUT:
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800358 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
359 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
360 if (event != IOC_E_PFFAILED)
361 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700362 break;
363
364 case IOC_E_DISABLE:
365 bfa_ioc_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700366 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
367 break;
368
369 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700370 break;
371
372 default:
373 bfa_sm_fault(ioc, event);
374 }
375}
376
377
378static void
379bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
380{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700381 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
382
Jing Huang7725ccf2009-09-23 17:46:15 -0700383 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
384 bfa_ioc_hb_monitor(ioc);
Jing Huang88166242010-12-09 17:11:53 -0800385 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700386}
387
388static void
389bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
390{
391 bfa_trc(ioc, event);
392
393 switch (event) {
394 case IOC_E_ENABLE:
395 break;
396
397 case IOC_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800398 bfa_hb_timer_stop(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700399 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
400 break;
401
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800402 case IOC_E_PFFAILED:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700403 case IOC_E_HWERROR:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800404 bfa_hb_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700405 /* !!! fall through !!! */
Jing Huang7725ccf2009-09-23 17:46:15 -0700406 case IOC_E_HBFAIL:
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800407 bfa_ioc_fail_notify(ioc);
408
409 if (ioc->iocpf.auto_recover)
410 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
411 else
412 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
413
414 if (event != IOC_E_PFFAILED)
415 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700416 break;
417
418 default:
419 bfa_sm_fault(ioc, event);
420 }
421}
422
423
424static void
425bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
426{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700427 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800428 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
Jing Huang88166242010-12-09 17:11:53 -0800429 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700430}
431
Jing Huang5fbe25c2010-10-18 17:17:23 -0700432/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700433 * IOC is being disabled
434 */
435static void
436bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
437{
438 bfa_trc(ioc, event);
439
440 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700441 case IOC_E_DISABLED:
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800442 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
443 break;
444
445 case IOC_E_HWERROR:
Jing Huang7725ccf2009-09-23 17:46:15 -0700446 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700447 * No state change. Will move to disabled state
448 * after iocpf sm completes failure processing and
449 * moves to disabled state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700450 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800451 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700452 break;
453
454 default:
455 bfa_sm_fault(ioc, event);
456 }
457}
458
Jing Huang5fbe25c2010-10-18 17:17:23 -0700459/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700460 * IOC disable completion entry.
461 */
462static void
463bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
464{
465 bfa_ioc_disable_comp(ioc);
466}
467
468static void
469bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
470{
471 bfa_trc(ioc, event);
472
473 switch (event) {
474 case IOC_E_ENABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700475 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700476 break;
477
478 case IOC_E_DISABLE:
479 ioc->cbfn->disable_cbfn(ioc->bfa);
480 break;
481
Jing Huang7725ccf2009-09-23 17:46:15 -0700482 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700483 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800484 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700485 break;
486
487 default:
488 bfa_sm_fault(ioc, event);
489 }
490}
491
492
493static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800494bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -0700495{
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800496 bfa_trc(ioc, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700497}
498
Jing Huang5fbe25c2010-10-18 17:17:23 -0700499/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700500 * Hardware initialization failed.
501 */
502static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800503bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700504{
505 bfa_trc(ioc, event);
506
507 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700508 case IOC_E_ENABLED:
509 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
510 break;
511
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800512 case IOC_E_PFFAILED:
513 case IOC_E_HWERROR:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700514 /*
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800515 * Initialization retry failed.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700516 */
517 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800518 if (event != IOC_E_PFFAILED)
519 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
520 break;
521
522 case IOC_E_ENABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700523 break;
524
Jing Huang7725ccf2009-09-23 17:46:15 -0700525 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700526 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700527 break;
528
529 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700530 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800531 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700532 break;
533
534 default:
535 bfa_sm_fault(ioc, event);
536 }
537}
538
539
540static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700541bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -0700542{
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800543 bfa_trc(ioc, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700544}
545
Jing Huang5fbe25c2010-10-18 17:17:23 -0700546/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700547 * IOC failure.
Jing Huang7725ccf2009-09-23 17:46:15 -0700548 */
549static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700550bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700551{
552 bfa_trc(ioc, event);
553
554 switch (event) {
555
556 case IOC_E_ENABLE:
557 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
558 break;
559
560 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700561 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700562 break;
563
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800564 case IOC_E_HWERROR:
565 /*
566 * HB failure notification, ignore.
567 */
568 break;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700569 default:
570 bfa_sm_fault(ioc, event);
571 }
572}
573
Jing Huang5fbe25c2010-10-18 17:17:23 -0700574/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700575 * IOCPF State Machine
576 */
577
Jing Huang5fbe25c2010-10-18 17:17:23 -0700578/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700579 * Reset entry actions -- initialize state machine
580 */
581static void
582bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
583{
584 iocpf->retry_count = 0;
585 iocpf->auto_recover = bfa_auto_recover;
586}
587
Jing Huang5fbe25c2010-10-18 17:17:23 -0700588/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700589 * Beginning state. IOC is in reset state.
590 */
591static void
592bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
593{
594 struct bfa_ioc_s *ioc = iocpf->ioc;
595
596 bfa_trc(ioc, event);
597
598 switch (event) {
599 case IOCPF_E_ENABLE:
600 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
601 break;
602
603 case IOCPF_E_STOP:
604 break;
605
606 default:
607 bfa_sm_fault(ioc, event);
608 }
609}
610
Jing Huang5fbe25c2010-10-18 17:17:23 -0700611/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700612 * Semaphore should be acquired for version check.
613 */
614static void
615bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
616{
617 bfa_ioc_hw_sem_get(iocpf->ioc);
618}
619
Jing Huang5fbe25c2010-10-18 17:17:23 -0700620/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700621 * Awaiting h/w semaphore to continue with version check.
622 */
623static void
624bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
625{
626 struct bfa_ioc_s *ioc = iocpf->ioc;
627
628 bfa_trc(ioc, event);
629
630 switch (event) {
631 case IOCPF_E_SEMLOCKED:
632 if (bfa_ioc_firmware_lock(ioc)) {
633 iocpf->retry_count = 0;
634 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
635 } else {
Maggie Zhangf7f73812010-12-09 19:08:43 -0800636 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700637 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
638 }
639 break;
640
641 case IOCPF_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800642 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700643 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800644 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700645 break;
646
647 case IOCPF_E_STOP:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800648 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700649 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
650 break;
651
652 default:
653 bfa_sm_fault(ioc, event);
654 }
655}
656
Jing Huang5fbe25c2010-10-18 17:17:23 -0700657/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700658 * Notify enable completion callback.
659 */
660static void
661bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
662{
663 /*
664 * Call only the first time sm enters fwmismatch state.
665 */
666 if (iocpf->retry_count == 0)
667 bfa_ioc_pf_fwmismatch(iocpf->ioc);
668
669 iocpf->retry_count++;
670 bfa_iocpf_timer_start(iocpf->ioc);
671}
672
Jing Huang5fbe25c2010-10-18 17:17:23 -0700673/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700674 * Awaiting firmware version match.
675 */
676static void
677bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
678{
679 struct bfa_ioc_s *ioc = iocpf->ioc;
680
681 bfa_trc(ioc, event);
682
683 switch (event) {
684 case IOCPF_E_TIMEOUT:
685 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
686 break;
687
688 case IOCPF_E_DISABLE:
689 bfa_iocpf_timer_stop(ioc);
690 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800691 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700692 break;
693
694 case IOCPF_E_STOP:
695 bfa_iocpf_timer_stop(ioc);
696 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
697 break;
698
699 default:
700 bfa_sm_fault(ioc, event);
701 }
702}
703
Jing Huang5fbe25c2010-10-18 17:17:23 -0700704/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700705 * Request for semaphore.
706 */
707static void
708bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
709{
710 bfa_ioc_hw_sem_get(iocpf->ioc);
711}
712
Jing Huang5fbe25c2010-10-18 17:17:23 -0700713/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700714 * Awaiting semaphore for h/w initialzation.
715 */
716static void
717bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
718{
719 struct bfa_ioc_s *ioc = iocpf->ioc;
720
721 bfa_trc(ioc, event);
722
723 switch (event) {
724 case IOCPF_E_SEMLOCKED:
725 iocpf->retry_count = 0;
726 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
727 break;
728
729 case IOCPF_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800730 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700731 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
732 break;
733
734 default:
735 bfa_sm_fault(ioc, event);
736 }
737}
738
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700739static void
740bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
741{
742 bfa_iocpf_timer_start(iocpf->ioc);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800743 bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700744}
745
Jing Huang5fbe25c2010-10-18 17:17:23 -0700746/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700747 * Hardware is being initialized. Interrupts are enabled.
748 * Holding hardware semaphore lock.
749 */
750static void
751bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
752{
753 struct bfa_ioc_s *ioc = iocpf->ioc;
754
755 bfa_trc(ioc, event);
756
757 switch (event) {
758 case IOCPF_E_FWREADY:
759 bfa_iocpf_timer_stop(ioc);
760 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
761 break;
762
763 case IOCPF_E_INITFAIL:
764 bfa_iocpf_timer_stop(ioc);
765 /*
766 * !!! fall through !!!
767 */
768
769 case IOCPF_E_TIMEOUT:
770 iocpf->retry_count++;
771 if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
772 bfa_iocpf_timer_start(ioc);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800773 bfa_ioc_hwinit(ioc, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700774 break;
775 }
776
Maggie Zhangf7f73812010-12-09 19:08:43 -0800777 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700778 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
779
780 if (event == IOCPF_E_TIMEOUT)
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800781 bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700782 break;
783
784 case IOCPF_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800785 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700786 bfa_iocpf_timer_stop(ioc);
787 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
788 break;
789
790 default:
791 bfa_sm_fault(ioc, event);
792 }
793}
794
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700795static void
796bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
797{
798 bfa_iocpf_timer_start(iocpf->ioc);
799 bfa_ioc_send_enable(iocpf->ioc);
800}
801
Jing Huang5fbe25c2010-10-18 17:17:23 -0700802/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700803 * Host IOC function is being enabled, awaiting response from firmware.
804 * Semaphore is acquired.
805 */
806static void
807bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
808{
809 struct bfa_ioc_s *ioc = iocpf->ioc;
810
811 bfa_trc(ioc, event);
812
813 switch (event) {
814 case IOCPF_E_FWRSP_ENABLE:
815 bfa_iocpf_timer_stop(ioc);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800816 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700817 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
818 break;
819
820 case IOCPF_E_INITFAIL:
821 bfa_iocpf_timer_stop(ioc);
822 /*
823 * !!! fall through !!!
824 */
825
826 case IOCPF_E_TIMEOUT:
827 iocpf->retry_count++;
828 if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
Jing Huang53440262010-10-18 17:12:29 -0700829 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700830 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
831 break;
832 }
833
Maggie Zhangf7f73812010-12-09 19:08:43 -0800834 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700835 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
836
837 if (event == IOCPF_E_TIMEOUT)
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800838 bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700839 break;
840
841 case IOCPF_E_DISABLE:
842 bfa_iocpf_timer_stop(ioc);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800843 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700844 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
845 break;
846
847 case IOCPF_E_FWREADY:
848 bfa_ioc_send_enable(ioc);
849 break;
850
851 default:
852 bfa_sm_fault(ioc, event);
853 }
854}
855
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700856static void
857bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
858{
Maggie Zhangf7f73812010-12-09 19:08:43 -0800859 bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700860}
861
862static void
863bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
864{
865 struct bfa_ioc_s *ioc = iocpf->ioc;
866
867 bfa_trc(ioc, event);
868
869 switch (event) {
870 case IOCPF_E_DISABLE:
871 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
872 break;
873
874 case IOCPF_E_GETATTRFAIL:
875 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
876 break;
877
878 case IOCPF_E_FAIL:
879 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
880 break;
881
882 case IOCPF_E_FWREADY:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800883 if (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700884 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
885 else
886 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
887
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800888 bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700889 break;
890
891 default:
892 bfa_sm_fault(ioc, event);
893 }
894}
895
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700896static void
897bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
898{
899 bfa_iocpf_timer_start(iocpf->ioc);
900 bfa_ioc_send_disable(iocpf->ioc);
901}
902
Jing Huang5fbe25c2010-10-18 17:17:23 -0700903/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700904 * IOC is being disabled
905 */
906static void
907bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
908{
909 struct bfa_ioc_s *ioc = iocpf->ioc;
910
911 bfa_trc(ioc, event);
912
913 switch (event) {
914 case IOCPF_E_FWRSP_DISABLE:
915 case IOCPF_E_FWREADY:
916 bfa_iocpf_timer_stop(ioc);
917 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
918 break;
919
920 case IOCPF_E_FAIL:
921 bfa_iocpf_timer_stop(ioc);
922 /*
923 * !!! fall through !!!
924 */
925
926 case IOCPF_E_TIMEOUT:
Jing Huang53440262010-10-18 17:12:29 -0700927 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700928 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
929 break;
930
931 case IOCPF_E_FWRSP_ENABLE:
932 break;
933
934 default:
935 bfa_sm_fault(ioc, event);
936 }
937}
938
Jing Huang5fbe25c2010-10-18 17:17:23 -0700939/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700940 * IOC disable completion entry.
941 */
942static void
943bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
944{
Maggie Zhangf7f73812010-12-09 19:08:43 -0800945 bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700946}
947
948static void
949bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
950{
951 struct bfa_ioc_s *ioc = iocpf->ioc;
952
953 bfa_trc(ioc, event);
954
955 switch (event) {
956 case IOCPF_E_ENABLE:
957 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
958 break;
959
960 case IOCPF_E_STOP:
961 bfa_ioc_firmware_unlock(ioc);
962 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
963 break;
964
965 default:
966 bfa_sm_fault(ioc, event);
967 }
968}
969
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700970static void
971bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
972{
973 bfa_iocpf_timer_start(iocpf->ioc);
974}
975
Jing Huang5fbe25c2010-10-18 17:17:23 -0700976/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700977 * Hardware initialization failed.
978 */
979static void
980bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
981{
982 struct bfa_ioc_s *ioc = iocpf->ioc;
983
984 bfa_trc(ioc, event);
985
986 switch (event) {
987 case IOCPF_E_DISABLE:
988 bfa_iocpf_timer_stop(ioc);
989 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
990 break;
991
992 case IOCPF_E_STOP:
993 bfa_iocpf_timer_stop(ioc);
994 bfa_ioc_firmware_unlock(ioc);
995 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
996 break;
997
998 case IOCPF_E_TIMEOUT:
999 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1000 break;
1001
1002 default:
1003 bfa_sm_fault(ioc, event);
1004 }
1005}
1006
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001007static void
1008bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
1009{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001010 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001011 * Mark IOC as failed in hardware and stop firmware.
1012 */
1013 bfa_ioc_lpu_stop(iocpf->ioc);
Jing Huang53440262010-10-18 17:12:29 -07001014 writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001015
Jing Huang5fbe25c2010-10-18 17:17:23 -07001016 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001017 * Notify other functions on HB failure.
1018 */
1019 bfa_ioc_notify_hbfail(iocpf->ioc);
1020
Jing Huang5fbe25c2010-10-18 17:17:23 -07001021 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001022 * Flush any queued up mailbox requests.
1023 */
1024 bfa_ioc_mbox_hbfail(iocpf->ioc);
1025
1026 if (iocpf->auto_recover)
1027 bfa_iocpf_recovery_timer_start(iocpf->ioc);
1028}
1029
Jing Huang5fbe25c2010-10-18 17:17:23 -07001030/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001031 * IOC is in failed state.
1032 */
1033static void
1034bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1035{
1036 struct bfa_ioc_s *ioc = iocpf->ioc;
1037
1038 bfa_trc(ioc, event);
1039
1040 switch (event) {
1041 case IOCPF_E_DISABLE:
1042 if (iocpf->auto_recover)
1043 bfa_iocpf_timer_stop(ioc);
1044 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1045 break;
1046
1047 case IOCPF_E_TIMEOUT:
1048 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1049 break;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001050
Jing Huang7725ccf2009-09-23 17:46:15 -07001051 default:
1052 bfa_sm_fault(ioc, event);
1053 }
1054}
1055
Jing Huang5fbe25c2010-10-18 17:17:23 -07001056/*
Maggie Zhangdf0f1932010-12-09 19:07:46 -08001057 * BFA IOC private functions
Jing Huang7725ccf2009-09-23 17:46:15 -07001058 */
1059
1060static void
1061bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
1062{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001063 struct list_head *qe;
1064 struct bfa_ioc_hbfail_notify_s *notify;
Jing Huang7725ccf2009-09-23 17:46:15 -07001065
1066 ioc->cbfn->disable_cbfn(ioc->bfa);
1067
Jing Huang5fbe25c2010-10-18 17:17:23 -07001068 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001069 * Notify common modules registered for notification.
1070 */
1071 list_for_each(qe, &ioc->hb_notify_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001072 notify = (struct bfa_ioc_hbfail_notify_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -07001073 notify->cbfn(notify->cbarg);
1074 }
1075}
1076
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001077bfa_boolean_t
Jing Huang53440262010-10-18 17:12:29 -07001078bfa_ioc_sem_get(void __iomem *sem_reg)
Jing Huang7725ccf2009-09-23 17:46:15 -07001079{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001080 u32 r32;
1081 int cnt = 0;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001082#define BFA_SEM_SPINCNT 3000
Jing Huang7725ccf2009-09-23 17:46:15 -07001083
Jing Huang53440262010-10-18 17:12:29 -07001084 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001085
1086 while (r32 && (cnt < BFA_SEM_SPINCNT)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001087 cnt++;
Jing Huang6a18b162010-10-18 17:08:54 -07001088 udelay(2);
Jing Huang53440262010-10-18 17:12:29 -07001089 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001090 }
1091
1092 if (r32 == 0)
1093 return BFA_TRUE;
1094
Jing Huang7725ccf2009-09-23 17:46:15 -07001095 bfa_assert(cnt < BFA_SEM_SPINCNT);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001096 return BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001097}
1098
Jing Huang7725ccf2009-09-23 17:46:15 -07001099static void
1100bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
1101{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001102 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001103
Jing Huang5fbe25c2010-10-18 17:17:23 -07001104 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001105 * First read to the semaphore register will return 0, subsequent reads
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001106 * will return 1. Semaphore is released by writing 1 to the register
Jing Huang7725ccf2009-09-23 17:46:15 -07001107 */
Jing Huang53440262010-10-18 17:12:29 -07001108 r32 = readl(ioc->ioc_regs.ioc_sem_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001109 if (r32 == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001110 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
Jing Huang7725ccf2009-09-23 17:46:15 -07001111 return;
1112 }
1113
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001114 bfa_sem_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001115}
1116
Jing Huang5fbe25c2010-10-18 17:17:23 -07001117/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001118 * Initialize LPU local memory (aka secondary memory / SRAM)
1119 */
1120static void
1121bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
1122{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001123 u32 pss_ctl;
1124 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001125#define PSS_LMEM_INIT_TIME 10000
1126
Jing Huang53440262010-10-18 17:12:29 -07001127 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001128 pss_ctl &= ~__PSS_LMEM_RESET;
1129 pss_ctl |= __PSS_LMEM_INIT_EN;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001130
1131 /*
1132 * i2c workaround 12.5khz clock
1133 */
1134 pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
Jing Huang53440262010-10-18 17:12:29 -07001135 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001136
Jing Huang5fbe25c2010-10-18 17:17:23 -07001137 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001138 * wait for memory initialization to be complete
1139 */
1140 i = 0;
1141 do {
Jing Huang53440262010-10-18 17:12:29 -07001142 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001143 i++;
1144 } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1145
Jing Huang5fbe25c2010-10-18 17:17:23 -07001146 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001147 * If memory initialization is not successful, IOC timeout will catch
1148 * such failures.
1149 */
1150 bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
1151 bfa_trc(ioc, pss_ctl);
1152
1153 pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
Jing Huang53440262010-10-18 17:12:29 -07001154 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001155}
1156
1157static void
1158bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
1159{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001160 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001161
Jing Huang5fbe25c2010-10-18 17:17:23 -07001162 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001163 * Take processor out of reset.
1164 */
Jing Huang53440262010-10-18 17:12:29 -07001165 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001166 pss_ctl &= ~__PSS_LPU0_RESET;
1167
Jing Huang53440262010-10-18 17:12:29 -07001168 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001169}
1170
1171static void
1172bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
1173{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001174 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001175
Jing Huang5fbe25c2010-10-18 17:17:23 -07001176 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001177 * Put processors in reset.
1178 */
Jing Huang53440262010-10-18 17:12:29 -07001179 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001180 pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1181
Jing Huang53440262010-10-18 17:12:29 -07001182 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001183}
1184
Jing Huang5fbe25c2010-10-18 17:17:23 -07001185/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001186 * Get driver and firmware versions.
1187 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001188void
Jing Huang7725ccf2009-09-23 17:46:15 -07001189bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1190{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001191 u32 pgnum, pgoff;
1192 u32 loff = 0;
1193 int i;
1194 u32 *fwsig = (u32 *) fwhdr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001195
Maggie Zhangf7f73812010-12-09 19:08:43 -08001196 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1197 pgoff = PSS_SMEM_PGOFF(loff);
Jing Huang53440262010-10-18 17:12:29 -07001198 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001199
1200 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
1201 i++) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001202 fwsig[i] =
1203 bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001204 loff += sizeof(u32);
1205 }
1206}
1207
Jing Huang5fbe25c2010-10-18 17:17:23 -07001208/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001209 * Returns TRUE if same.
1210 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001211bfa_boolean_t
Jing Huang7725ccf2009-09-23 17:46:15 -07001212bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1213{
1214 struct bfi_ioc_image_hdr_s *drv_fwhdr;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001215 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001216
Jing Huang293f82d2010-07-08 19:45:20 -07001217 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001218 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001219
1220 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1221 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
1222 bfa_trc(ioc, i);
1223 bfa_trc(ioc, fwhdr->md5sum[i]);
1224 bfa_trc(ioc, drv_fwhdr->md5sum[i]);
1225 return BFA_FALSE;
1226 }
1227 }
1228
1229 bfa_trc(ioc, fwhdr->md5sum[0]);
1230 return BFA_TRUE;
1231}
1232
Jing Huang5fbe25c2010-10-18 17:17:23 -07001233/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001234 * Return true if current running version is valid. Firmware signature and
1235 * execution context (driver/bios) must match.
1236 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001237static bfa_boolean_t
1238bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001239{
1240 struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
1241
Jing Huang5fbe25c2010-10-18 17:17:23 -07001242 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001243 * If bios/efi boot (flash based) -- return true
1244 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001245 if (bfa_ioc_is_bios_optrom(ioc))
Jing Huang7725ccf2009-09-23 17:46:15 -07001246 return BFA_TRUE;
1247
1248 bfa_ioc_fwver_get(ioc, &fwhdr);
Jing Huang293f82d2010-07-08 19:45:20 -07001249 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001250 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001251
1252 if (fwhdr.signature != drv_fwhdr->signature) {
1253 bfa_trc(ioc, fwhdr.signature);
1254 bfa_trc(ioc, drv_fwhdr->signature);
1255 return BFA_FALSE;
1256 }
1257
Jing Huang53440262010-10-18 17:12:29 -07001258 if (swab32(fwhdr.param) != boot_env) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001259 bfa_trc(ioc, fwhdr.param);
1260 bfa_trc(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001261 return BFA_FALSE;
1262 }
1263
1264 return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1265}
1266
Jing Huang5fbe25c2010-10-18 17:17:23 -07001267/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001268 * Conditionally flush any pending message from firmware at start.
1269 */
1270static void
1271bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1272{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001273 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001274
Jing Huang53440262010-10-18 17:12:29 -07001275 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001276 if (r32)
Jing Huang53440262010-10-18 17:12:29 -07001277 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001278}
1279
Jing Huang7725ccf2009-09-23 17:46:15 -07001280static void
1281bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1282{
1283 enum bfi_ioc_state ioc_fwstate;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001284 bfa_boolean_t fwvalid;
1285 u32 boot_type;
1286 u32 boot_env;
Jing Huang7725ccf2009-09-23 17:46:15 -07001287
Jing Huang53440262010-10-18 17:12:29 -07001288 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07001289
1290 if (force)
1291 ioc_fwstate = BFI_IOC_UNINIT;
1292
1293 bfa_trc(ioc, ioc_fwstate);
1294
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001295 boot_type = BFI_BOOT_TYPE_NORMAL;
1296 boot_env = BFI_BOOT_LOADER_OS;
1297
Jing Huang5fbe25c2010-10-18 17:17:23 -07001298 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001299 * Flash based firmware boot BIOS env.
1300 */
1301 if (bfa_ioc_is_bios_optrom(ioc)) {
1302 boot_type = BFI_BOOT_TYPE_FLASH;
1303 boot_env = BFI_BOOT_LOADER_BIOS;
1304 }
1305
Jing Huang5fbe25c2010-10-18 17:17:23 -07001306 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001307 * Flash based firmware boot UEFI env.
1308 */
1309 if (bfa_ioc_is_uefi(ioc)) {
1310 boot_type = BFI_BOOT_TYPE_FLASH;
1311 boot_env = BFI_BOOT_LOADER_UEFI;
1312 }
1313
Jing Huang5fbe25c2010-10-18 17:17:23 -07001314 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001315 * check if firmware is valid
1316 */
1317 fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001318 BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001319
1320 if (!fwvalid) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001321 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001322 return;
1323 }
1324
Jing Huang5fbe25c2010-10-18 17:17:23 -07001325 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001326 * If hardware initialization is in progress (initialized by other IOC),
1327 * just wait for an initialization completion interrupt.
1328 */
1329 if (ioc_fwstate == BFI_IOC_INITING) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001330 ioc->cbfn->reset_cbfn(ioc->bfa);
1331 return;
1332 }
1333
Jing Huang5fbe25c2010-10-18 17:17:23 -07001334 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001335 * If IOC function is disabled and firmware version is same,
1336 * just re-enable IOC.
Jing Huang07b28382010-07-08 19:59:24 -07001337 *
1338 * If option rom, IOC must not be in operational state. With
1339 * convergence, IOC will be in operational state when 2nd driver
1340 * is loaded.
Jing Huang7725ccf2009-09-23 17:46:15 -07001341 */
Jing Huang07b28382010-07-08 19:59:24 -07001342 if (ioc_fwstate == BFI_IOC_DISABLED ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001343 (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001344
Jing Huang5fbe25c2010-10-18 17:17:23 -07001345 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001346 * When using MSI-X any pending firmware ready event should
1347 * be flushed. Otherwise MSI-X interrupts are not delivered.
1348 */
1349 bfa_ioc_msgflush(ioc);
1350 ioc->cbfn->reset_cbfn(ioc->bfa);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001351 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001352 return;
1353 }
1354
Jing Huang5fbe25c2010-10-18 17:17:23 -07001355 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001356 * Initialize the h/w for any other states.
1357 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001358 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001359}
1360
1361static void
1362bfa_ioc_timeout(void *ioc_arg)
1363{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001364 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -07001365
1366 bfa_trc(ioc, 0);
1367 bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1368}
1369
1370void
1371bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1372{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001373 u32 *msgp = (u32 *) ioc_msg;
1374 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001375
1376 bfa_trc(ioc, msgp[0]);
1377 bfa_trc(ioc, len);
1378
1379 bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
1380
1381 /*
1382 * first write msg to mailbox registers
1383 */
1384 for (i = 0; i < len / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001385 writel(cpu_to_le32(msgp[i]),
1386 ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001387
1388 for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001389 writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001390
1391 /*
1392 * write 1 to mailbox CMD to trigger LPU event
1393 */
Jing Huang53440262010-10-18 17:12:29 -07001394 writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1395 (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001396}
1397
1398static void
1399bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1400{
1401 struct bfi_ioc_ctrl_req_s enable_req;
Maggie Zhangf16a1752010-12-09 19:12:32 -08001402 struct timeval tv;
Jing Huang7725ccf2009-09-23 17:46:15 -07001403
1404 bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1405 bfa_ioc_portid(ioc));
1406 enable_req.ioc_class = ioc->ioc_mc;
Maggie Zhangf16a1752010-12-09 19:12:32 -08001407 do_gettimeofday(&tv);
Jing Huangba816ea2010-10-18 17:10:50 -07001408 enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
Jing Huang7725ccf2009-09-23 17:46:15 -07001409 bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1410}
1411
1412static void
1413bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1414{
1415 struct bfi_ioc_ctrl_req_s disable_req;
1416
1417 bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1418 bfa_ioc_portid(ioc));
1419 bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1420}
1421
1422static void
1423bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1424{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001425 struct bfi_ioc_getattr_req_s attr_req;
Jing Huang7725ccf2009-09-23 17:46:15 -07001426
1427 bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1428 bfa_ioc_portid(ioc));
1429 bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1430 bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1431}
1432
1433static void
1434bfa_ioc_hb_check(void *cbarg)
1435{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001436 struct bfa_ioc_s *ioc = cbarg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001437 u32 hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001438
Jing Huang53440262010-10-18 17:12:29 -07001439 hb_count = readl(ioc->ioc_regs.heartbeat);
Jing Huang7725ccf2009-09-23 17:46:15 -07001440 if (ioc->hb_count == hb_count) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001441 printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
Jing Huang7725ccf2009-09-23 17:46:15 -07001442 bfa_ioc_recover(ioc);
1443 return;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001444 } else {
1445 ioc->hb_count = hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001446 }
1447
1448 bfa_ioc_mbox_poll(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001449 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001450}
1451
1452static void
1453bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1454{
Jing Huang53440262010-10-18 17:12:29 -07001455 ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001456 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001457}
1458
Jing Huang5fbe25c2010-10-18 17:17:23 -07001459/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001460 * Initiate a full firmware download.
Jing Huang7725ccf2009-09-23 17:46:15 -07001461 */
1462static void
1463bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001464 u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001465{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001466 u32 *fwimg;
1467 u32 pgnum, pgoff;
1468 u32 loff = 0;
1469 u32 chunkno = 0;
1470 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001471
Jing Huang5fbe25c2010-10-18 17:17:23 -07001472 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001473 * Initialize LMEM first before code download
1474 */
1475 bfa_ioc_lmem_init(ioc);
1476
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001477 bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
1478 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
Jing Huang7725ccf2009-09-23 17:46:15 -07001479
Maggie Zhangf7f73812010-12-09 19:08:43 -08001480 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1481 pgoff = PSS_SMEM_PGOFF(loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001482
Jing Huang53440262010-10-18 17:12:29 -07001483 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001484
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001485 for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001486
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001487 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1488 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001489 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001490 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
Jing Huang7725ccf2009-09-23 17:46:15 -07001491 }
1492
Jing Huang5fbe25c2010-10-18 17:17:23 -07001493 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001494 * write smem
1495 */
1496 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001497 fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
Jing Huang7725ccf2009-09-23 17:46:15 -07001498
1499 loff += sizeof(u32);
1500
Jing Huang5fbe25c2010-10-18 17:17:23 -07001501 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001502 * handle page offset wrap around
1503 */
1504 loff = PSS_SMEM_PGOFF(loff);
1505 if (loff == 0) {
1506 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001507 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001508 }
1509 }
1510
Maggie Zhangf7f73812010-12-09 19:08:43 -08001511 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1512 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001513
1514 /*
1515 * Set boot type and boot param at the end.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001516 */
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001517 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001518 swab32(boot_type));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001519 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001520 swab32(boot_env));
Jing Huang7725ccf2009-09-23 17:46:15 -07001521}
1522
Jing Huang7725ccf2009-09-23 17:46:15 -07001523
Jing Huang5fbe25c2010-10-18 17:17:23 -07001524/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001525 * Update BFA configuration from firmware configuration.
1526 */
1527static void
1528bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1529{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001530 struct bfi_ioc_attr_s *attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001531
Jing Huangba816ea2010-10-18 17:10:50 -07001532 attr->adapter_prop = be32_to_cpu(attr->adapter_prop);
1533 attr->card_type = be32_to_cpu(attr->card_type);
1534 attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
Jing Huang7725ccf2009-09-23 17:46:15 -07001535
1536 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1537}
1538
Jing Huang5fbe25c2010-10-18 17:17:23 -07001539/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001540 * Attach time initialization of mbox logic.
1541 */
1542static void
1543bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1544{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001545 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1546 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001547
1548 INIT_LIST_HEAD(&mod->cmd_q);
1549 for (mc = 0; mc < BFI_MC_MAX; mc++) {
1550 mod->mbhdlr[mc].cbfn = NULL;
1551 mod->mbhdlr[mc].cbarg = ioc->bfa;
1552 }
1553}
1554
Jing Huang5fbe25c2010-10-18 17:17:23 -07001555/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001556 * Mbox poll timer -- restarts any pending mailbox requests.
1557 */
1558static void
1559bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1560{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001561 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1562 struct bfa_mbox_cmd_s *cmd;
1563 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07001564
Jing Huang5fbe25c2010-10-18 17:17:23 -07001565 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001566 * If no command pending, do nothing
1567 */
1568 if (list_empty(&mod->cmd_q))
1569 return;
1570
Jing Huang5fbe25c2010-10-18 17:17:23 -07001571 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001572 * If previous command is not yet fetched by firmware, do nothing
1573 */
Jing Huang53440262010-10-18 17:12:29 -07001574 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001575 if (stat)
1576 return;
1577
Jing Huang5fbe25c2010-10-18 17:17:23 -07001578 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001579 * Enqueue command to firmware.
1580 */
1581 bfa_q_deq(&mod->cmd_q, &cmd);
1582 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1583}
1584
Jing Huang5fbe25c2010-10-18 17:17:23 -07001585/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001586 * Cleanup any pending requests.
1587 */
1588static void
1589bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
1590{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001591 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1592 struct bfa_mbox_cmd_s *cmd;
Jing Huang7725ccf2009-09-23 17:46:15 -07001593
1594 while (!list_empty(&mod->cmd_q))
1595 bfa_q_deq(&mod->cmd_q, &cmd);
1596}
1597
Jing Huang5fbe25c2010-10-18 17:17:23 -07001598/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001599 * Read data from SMEM to host through PCI memmap
1600 *
1601 * @param[in] ioc memory for IOC
1602 * @param[in] tbuf app memory to store data from smem
1603 * @param[in] soff smem offset
1604 * @param[in] sz size of smem in bytes
Jing Huang7725ccf2009-09-23 17:46:15 -07001605 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001606static bfa_status_t
1607bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
1608{
Maggie50444a32010-11-29 18:26:32 -08001609 u32 pgnum, loff;
1610 __be32 r32;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001611 int i, len;
1612 u32 *buf = tbuf;
1613
Maggie Zhangf7f73812010-12-09 19:08:43 -08001614 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1615 loff = PSS_SMEM_PGOFF(soff);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001616 bfa_trc(ioc, pgnum);
1617 bfa_trc(ioc, loff);
1618 bfa_trc(ioc, sz);
1619
1620 /*
1621 * Hold semaphore to serialize pll init and fwtrc.
1622 */
1623 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1624 bfa_trc(ioc, 0);
1625 return BFA_STATUS_FAILED;
1626 }
1627
Jing Huang53440262010-10-18 17:12:29 -07001628 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001629
1630 len = sz/sizeof(u32);
1631 bfa_trc(ioc, len);
1632 for (i = 0; i < len; i++) {
1633 r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huangba816ea2010-10-18 17:10:50 -07001634 buf[i] = be32_to_cpu(r32);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001635 loff += sizeof(u32);
1636
Jing Huang5fbe25c2010-10-18 17:17:23 -07001637 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001638 * handle page offset wrap around
1639 */
1640 loff = PSS_SMEM_PGOFF(loff);
1641 if (loff == 0) {
1642 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001643 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001644 }
1645 }
Maggie Zhangf7f73812010-12-09 19:08:43 -08001646 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1647 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001648 /*
1649 * release semaphore.
1650 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08001651 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001652
1653 bfa_trc(ioc, pgnum);
1654 return BFA_STATUS_OK;
1655}
1656
Jing Huang5fbe25c2010-10-18 17:17:23 -07001657/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001658 * Clear SMEM data from host through PCI memmap
1659 *
1660 * @param[in] ioc memory for IOC
1661 * @param[in] soff smem offset
1662 * @param[in] sz size of smem in bytes
1663 */
1664static bfa_status_t
1665bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
1666{
1667 int i, len;
1668 u32 pgnum, loff;
1669
Maggie Zhangf7f73812010-12-09 19:08:43 -08001670 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1671 loff = PSS_SMEM_PGOFF(soff);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001672 bfa_trc(ioc, pgnum);
1673 bfa_trc(ioc, loff);
1674 bfa_trc(ioc, sz);
1675
1676 /*
1677 * Hold semaphore to serialize pll init and fwtrc.
1678 */
1679 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1680 bfa_trc(ioc, 0);
1681 return BFA_STATUS_FAILED;
1682 }
1683
Jing Huang53440262010-10-18 17:12:29 -07001684 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001685
1686 len = sz/sizeof(u32); /* len in words */
1687 bfa_trc(ioc, len);
1688 for (i = 0; i < len; i++) {
1689 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
1690 loff += sizeof(u32);
1691
Jing Huang5fbe25c2010-10-18 17:17:23 -07001692 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001693 * handle page offset wrap around
1694 */
1695 loff = PSS_SMEM_PGOFF(loff);
1696 if (loff == 0) {
1697 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001698 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001699 }
1700 }
Maggie Zhangf7f73812010-12-09 19:08:43 -08001701 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1702 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001703
1704 /*
1705 * release semaphore.
1706 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08001707 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001708 bfa_trc(ioc, pgnum);
1709 return BFA_STATUS_OK;
1710}
1711
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001712static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08001713bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
1714{
1715 struct list_head *qe;
1716 struct bfa_ioc_hbfail_notify_s *notify;
1717 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
1718
1719 /**
1720 * Notify driver and common modules registered for notification.
1721 */
1722 ioc->cbfn->hbfail_cbfn(ioc->bfa);
1723 list_for_each(qe, &ioc->hb_notify_q) {
1724 notify = (struct bfa_ioc_hbfail_notify_s *) qe;
1725 notify->cbfn(notify->cbarg);
1726 }
1727
1728 bfa_ioc_debug_save_ftrc(ioc);
1729
1730 BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
1731 "Heart Beat of IOC has failed\n");
1732
1733}
1734
1735static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001736bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
1737{
1738 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Jing Huang5fbe25c2010-10-18 17:17:23 -07001739 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001740 * Provide enable completion callback.
1741 */
1742 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Jing Huang88166242010-12-09 17:11:53 -08001743 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001744 "Running firmware version is incompatible "
1745 "with the driver version\n");
1746}
1747
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001748bfa_status_t
1749bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1750{
1751
1752 /*
1753 * Hold semaphore so that nobody can access the chip during init.
1754 */
1755 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1756
1757 bfa_ioc_pll_init_asic(ioc);
1758
1759 ioc->pllinit = BFA_TRUE;
1760 /*
1761 * release semaphore.
1762 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08001763 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001764
1765 return BFA_STATUS_OK;
1766}
Jing Huang7725ccf2009-09-23 17:46:15 -07001767
Jing Huang5fbe25c2010-10-18 17:17:23 -07001768/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001769 * Interface used by diag module to do firmware boot with memory test
1770 * as the entry vector.
1771 */
1772void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001773bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001774{
Jing Huang53440262010-10-18 17:12:29 -07001775 void __iomem *rb;
Jing Huang7725ccf2009-09-23 17:46:15 -07001776
1777 bfa_ioc_stats(ioc, ioc_boots);
1778
1779 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1780 return;
1781
Jing Huang5fbe25c2010-10-18 17:17:23 -07001782 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001783 * Initialize IOC state of all functions on a chip reset.
1784 */
1785 rb = ioc->pcidev.pci_bar_kva;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001786 if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
Jing Huang53440262010-10-18 17:12:29 -07001787 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
1788 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
Jing Huang7725ccf2009-09-23 17:46:15 -07001789 } else {
Jing Huang53440262010-10-18 17:12:29 -07001790 writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
1791 writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
Jing Huang7725ccf2009-09-23 17:46:15 -07001792 }
1793
Jing Huang07b28382010-07-08 19:59:24 -07001794 bfa_ioc_msgflush(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001795 bfa_ioc_download_fw(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001796
Jing Huang5fbe25c2010-10-18 17:17:23 -07001797 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001798 * Enable interrupts just before starting LPU
1799 */
1800 ioc->cbfn->reset_cbfn(ioc->bfa);
1801 bfa_ioc_lpu_start(ioc);
1802}
1803
Jing Huang5fbe25c2010-10-18 17:17:23 -07001804/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001805 * Enable/disable IOC failure auto recovery.
1806 */
1807void
1808bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
1809{
Krishna Gudipati2f9b8852010-03-03 17:42:51 -08001810 bfa_auto_recover = auto_recover;
Jing Huang7725ccf2009-09-23 17:46:15 -07001811}
1812
1813
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001814
Jing Huang7725ccf2009-09-23 17:46:15 -07001815bfa_boolean_t
1816bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
1817{
1818 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
1819}
1820
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001821bfa_boolean_t
1822bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
1823{
Jing Huang53440262010-10-18 17:12:29 -07001824 u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001825
1826 return ((r32 != BFI_IOC_UNINIT) &&
1827 (r32 != BFI_IOC_INITING) &&
1828 (r32 != BFI_IOC_MEMTEST));
1829}
1830
Jing Huang7725ccf2009-09-23 17:46:15 -07001831void
1832bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
1833{
Maggie50444a32010-11-29 18:26:32 -08001834 __be32 *msgp = mbmsg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001835 u32 r32;
1836 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001837
Jing Huang5fbe25c2010-10-18 17:17:23 -07001838 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001839 * read the MBOX msg
1840 */
1841 for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
1842 i++) {
Jing Huang53440262010-10-18 17:12:29 -07001843 r32 = readl(ioc->ioc_regs.lpu_mbox +
Jing Huang7725ccf2009-09-23 17:46:15 -07001844 i * sizeof(u32));
Jing Huangba816ea2010-10-18 17:10:50 -07001845 msgp[i] = cpu_to_be32(r32);
Jing Huang7725ccf2009-09-23 17:46:15 -07001846 }
1847
Jing Huang5fbe25c2010-10-18 17:17:23 -07001848 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001849 * turn off mailbox interrupt by clearing mailbox status
1850 */
Jing Huang53440262010-10-18 17:12:29 -07001851 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1852 readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001853}
1854
1855void
1856bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
1857{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001858 union bfi_ioc_i2h_msg_u *msg;
1859 struct bfa_iocpf_s *iocpf = &ioc->iocpf;
Jing Huang7725ccf2009-09-23 17:46:15 -07001860
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001861 msg = (union bfi_ioc_i2h_msg_u *) m;
Jing Huang7725ccf2009-09-23 17:46:15 -07001862
1863 bfa_ioc_stats(ioc, ioc_isrs);
1864
1865 switch (msg->mh.msg_id) {
1866 case BFI_IOC_I2H_HBEAT:
1867 break;
1868
1869 case BFI_IOC_I2H_READY_EVENT:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001870 bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001871 break;
1872
1873 case BFI_IOC_I2H_ENABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001874 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001875 break;
1876
1877 case BFI_IOC_I2H_DISABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001878 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001879 break;
1880
1881 case BFI_IOC_I2H_GETATTR_REPLY:
1882 bfa_ioc_getattr_reply(ioc);
1883 break;
1884
1885 default:
1886 bfa_trc(ioc, msg->mh.msg_id);
1887 bfa_assert(0);
1888 }
1889}
1890
Jing Huang5fbe25c2010-10-18 17:17:23 -07001891/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001892 * IOC attach time initialization and setup.
1893 *
1894 * @param[in] ioc memory for IOC
1895 * @param[in] bfa driver instance structure
Jing Huang7725ccf2009-09-23 17:46:15 -07001896 */
1897void
1898bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001899 struct bfa_timer_mod_s *timer_mod)
Jing Huang7725ccf2009-09-23 17:46:15 -07001900{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001901 ioc->bfa = bfa;
1902 ioc->cbfn = cbfn;
1903 ioc->timer_mod = timer_mod;
1904 ioc->fcmode = BFA_FALSE;
1905 ioc->pllinit = BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001906 ioc->dbg_fwsave_once = BFA_TRUE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001907 ioc->iocpf.ioc = ioc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001908
1909 bfa_ioc_mbox_attach(ioc);
1910 INIT_LIST_HEAD(&ioc->hb_notify_q);
1911
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001912 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
1913 bfa_fsm_send_event(ioc, IOC_E_RESET);
Jing Huang7725ccf2009-09-23 17:46:15 -07001914}
1915
Jing Huang5fbe25c2010-10-18 17:17:23 -07001916/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001917 * Driver detach time IOC cleanup.
1918 */
1919void
1920bfa_ioc_detach(struct bfa_ioc_s *ioc)
1921{
1922 bfa_fsm_send_event(ioc, IOC_E_DETACH);
1923}
1924
Jing Huang5fbe25c2010-10-18 17:17:23 -07001925/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001926 * Setup IOC PCI properties.
1927 *
1928 * @param[in] pcidev PCI device information for this IOC
1929 */
1930void
1931bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
1932 enum bfi_mclass mc)
1933{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001934 ioc->ioc_mc = mc;
1935 ioc->pcidev = *pcidev;
1936 ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
1937 ioc->cna = ioc->ctdev && !ioc->fcmode;
Jing Huang7725ccf2009-09-23 17:46:15 -07001938
Jing Huang5fbe25c2010-10-18 17:17:23 -07001939 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001940 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
1941 */
1942 if (ioc->ctdev)
1943 bfa_ioc_set_ct_hwif(ioc);
1944 else
1945 bfa_ioc_set_cb_hwif(ioc);
1946
Jing Huang7725ccf2009-09-23 17:46:15 -07001947 bfa_ioc_map_port(ioc);
1948 bfa_ioc_reg_init(ioc);
1949}
1950
Jing Huang5fbe25c2010-10-18 17:17:23 -07001951/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001952 * Initialize IOC dma memory
1953 *
1954 * @param[in] dm_kva kernel virtual address of IOC dma memory
1955 * @param[in] dm_pa physical address of IOC dma memory
1956 */
1957void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001958bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
Jing Huang7725ccf2009-09-23 17:46:15 -07001959{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001960 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001961 * dma memory for firmware attribute
1962 */
1963 ioc->attr_dma.kva = dm_kva;
1964 ioc->attr_dma.pa = dm_pa;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001965 ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07001966}
1967
Jing Huang7725ccf2009-09-23 17:46:15 -07001968void
1969bfa_ioc_enable(struct bfa_ioc_s *ioc)
1970{
1971 bfa_ioc_stats(ioc, ioc_enables);
1972 ioc->dbg_fwsave_once = BFA_TRUE;
1973
1974 bfa_fsm_send_event(ioc, IOC_E_ENABLE);
1975}
1976
1977void
1978bfa_ioc_disable(struct bfa_ioc_s *ioc)
1979{
1980 bfa_ioc_stats(ioc, ioc_disables);
1981 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
1982}
1983
Jing Huang7725ccf2009-09-23 17:46:15 -07001984
Jing Huang5fbe25c2010-10-18 17:17:23 -07001985/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001986 * Initialize memory for saving firmware trace. Driver must initialize
1987 * trace memory before call bfa_ioc_enable().
1988 */
1989void
1990bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
1991{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001992 ioc->dbg_fwsave = dbg_fwsave;
Maggie Zhangf7f73812010-12-09 19:08:43 -08001993 ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
Jing Huang7725ccf2009-09-23 17:46:15 -07001994}
1995
Jing Huang5fbe25c2010-10-18 17:17:23 -07001996/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001997 * Register mailbox message handler functions
1998 *
1999 * @param[in] ioc IOC instance
2000 * @param[in] mcfuncs message class handler functions
2001 */
2002void
2003bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
2004{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002005 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2006 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002007
2008 for (mc = 0; mc < BFI_MC_MAX; mc++)
2009 mod->mbhdlr[mc].cbfn = mcfuncs[mc];
2010}
2011
Jing Huang5fbe25c2010-10-18 17:17:23 -07002012/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002013 * Register mailbox message handler function, to be called by common modules
2014 */
2015void
2016bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
2017 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2018{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002019 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
Jing Huang7725ccf2009-09-23 17:46:15 -07002020
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002021 mod->mbhdlr[mc].cbfn = cbfn;
2022 mod->mbhdlr[mc].cbarg = cbarg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002023}
2024
Jing Huang5fbe25c2010-10-18 17:17:23 -07002025/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002026 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2027 * Responsibility of caller to serialize
2028 *
2029 * @param[in] ioc IOC instance
2030 * @param[i] cmd Mailbox command
2031 */
2032void
2033bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
2034{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002035 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2036 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07002037
Jing Huang5fbe25c2010-10-18 17:17:23 -07002038 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002039 * If a previous command is pending, queue new command
2040 */
2041 if (!list_empty(&mod->cmd_q)) {
2042 list_add_tail(&cmd->qe, &mod->cmd_q);
2043 return;
2044 }
2045
Jing Huang5fbe25c2010-10-18 17:17:23 -07002046 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002047 * If mailbox is busy, queue command for poll timer
2048 */
Jing Huang53440262010-10-18 17:12:29 -07002049 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07002050 if (stat) {
2051 list_add_tail(&cmd->qe, &mod->cmd_q);
2052 return;
2053 }
2054
Jing Huang5fbe25c2010-10-18 17:17:23 -07002055 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002056 * mailbox is free -- queue command to firmware
2057 */
2058 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
2059}
2060
Jing Huang5fbe25c2010-10-18 17:17:23 -07002061/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002062 * Handle mailbox interrupts
2063 */
2064void
2065bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
2066{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002067 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2068 struct bfi_mbmsg_s m;
2069 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002070
2071 bfa_ioc_msgget(ioc, &m);
2072
Jing Huang5fbe25c2010-10-18 17:17:23 -07002073 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002074 * Treat IOC message class as special.
2075 */
2076 mc = m.mh.msg_class;
2077 if (mc == BFI_MC_IOC) {
2078 bfa_ioc_isr(ioc, &m);
2079 return;
2080 }
2081
2082 if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2083 return;
2084
2085 mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
2086}
2087
2088void
2089bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
2090{
2091 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2092}
2093
Jing Huanged969322010-07-08 19:45:56 -07002094void
2095bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
2096{
2097 ioc->fcmode = BFA_TRUE;
2098 ioc->port_id = bfa_ioc_pcifn(ioc);
2099}
2100
Jing Huang5fbe25c2010-10-18 17:17:23 -07002101/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002102 * return true if IOC is disabled
2103 */
2104bfa_boolean_t
2105bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
2106{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002107 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2108 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
Jing Huang7725ccf2009-09-23 17:46:15 -07002109}
2110
Jing Huang5fbe25c2010-10-18 17:17:23 -07002111/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002112 * return true if IOC firmware is different.
2113 */
2114bfa_boolean_t
2115bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2116{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002117 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
2118 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
2119 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
Jing Huang7725ccf2009-09-23 17:46:15 -07002120}
2121
2122#define bfa_ioc_state_disabled(__sm) \
2123 (((__sm) == BFI_IOC_UNINIT) || \
2124 ((__sm) == BFI_IOC_INITING) || \
2125 ((__sm) == BFI_IOC_HWINIT) || \
2126 ((__sm) == BFI_IOC_DISABLED) || \
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002127 ((__sm) == BFI_IOC_FAIL) || \
Jing Huang7725ccf2009-09-23 17:46:15 -07002128 ((__sm) == BFI_IOC_CFG_DISABLED))
2129
Jing Huang5fbe25c2010-10-18 17:17:23 -07002130/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002131 * Check if adapter is disabled -- both IOCs should be in a disabled
2132 * state.
2133 */
2134bfa_boolean_t
2135bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
2136{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002137 u32 ioc_state;
Jing Huang53440262010-10-18 17:12:29 -07002138 void __iomem *rb = ioc->pcidev.pci_bar_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07002139
2140 if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
2141 return BFA_FALSE;
2142
Jing Huang53440262010-10-18 17:12:29 -07002143 ioc_state = readl(rb + BFA_IOC0_STATE_REG);
Jing Huang7725ccf2009-09-23 17:46:15 -07002144 if (!bfa_ioc_state_disabled(ioc_state))
2145 return BFA_FALSE;
2146
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002147 if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
Jing Huang53440262010-10-18 17:12:29 -07002148 ioc_state = readl(rb + BFA_IOC1_STATE_REG);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002149 if (!bfa_ioc_state_disabled(ioc_state))
2150 return BFA_FALSE;
2151 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002152
2153 return BFA_TRUE;
2154}
2155
Jing Huang7725ccf2009-09-23 17:46:15 -07002156#define BFA_MFG_NAME "Brocade"
2157void
2158bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2159 struct bfa_adapter_attr_s *ad_attr)
2160{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002161 struct bfi_ioc_attr_s *ioc_attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002162
2163 ioc_attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002164
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002165 bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2166 bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2167 bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2168 bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
Jing Huang6a18b162010-10-18 17:08:54 -07002169 memcpy(&ad_attr->vpd, &ioc_attr->vpd,
Jing Huang7725ccf2009-09-23 17:46:15 -07002170 sizeof(struct bfa_mfg_vpd_s));
2171
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002172 ad_attr->nports = bfa_ioc_get_nports(ioc);
2173 ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002174
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002175 bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2176 /* For now, model descr uses same model string */
2177 bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
Jing Huang7725ccf2009-09-23 17:46:15 -07002178
Jing Huanged969322010-07-08 19:45:56 -07002179 ad_attr->card_type = ioc_attr->card_type;
2180 ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2181
Jing Huang7725ccf2009-09-23 17:46:15 -07002182 if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2183 ad_attr->prototype = 1;
2184 else
2185 ad_attr->prototype = 0;
2186
Maggie Zhangf7f73812010-12-09 19:08:43 -08002187 ad_attr->pwwn = ioc->attr->pwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002188 ad_attr->mac = bfa_ioc_get_mac(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002189
2190 ad_attr->pcie_gen = ioc_attr->pcie_gen;
2191 ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2192 ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2193 ad_attr->asic_rev = ioc_attr->asic_rev;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002194
2195 bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
Jing Huang7725ccf2009-09-23 17:46:15 -07002196
2197 ad_attr->cna_capable = ioc->cna;
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08002198 ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna &&
2199 !ad_attr->is_mezz;
Jing Huang7725ccf2009-09-23 17:46:15 -07002200}
2201
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002202enum bfa_ioc_type_e
2203bfa_ioc_get_type(struct bfa_ioc_s *ioc)
2204{
2205 if (!ioc->ctdev || ioc->fcmode)
2206 return BFA_IOC_TYPE_FC;
2207 else if (ioc->ioc_mc == BFI_MC_IOCFC)
2208 return BFA_IOC_TYPE_FCoE;
2209 else if (ioc->ioc_mc == BFI_MC_LL)
2210 return BFA_IOC_TYPE_LL;
2211 else {
2212 bfa_assert(ioc->ioc_mc == BFI_MC_LL);
2213 return BFA_IOC_TYPE_LL;
2214 }
2215}
2216
Jing Huang7725ccf2009-09-23 17:46:15 -07002217void
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002218bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)
2219{
Jing Huang6a18b162010-10-18 17:08:54 -07002220 memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2221 memcpy((void *)serial_num,
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002222 (void *)ioc->attr->brcd_serialnum,
2223 BFA_ADAPTER_SERIAL_NUM_LEN);
2224}
2225
2226void
2227bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
2228{
Jing Huang6a18b162010-10-18 17:08:54 -07002229 memset((void *)fw_ver, 0, BFA_VERSION_LEN);
2230 memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002231}
2232
2233void
2234bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
2235{
2236 bfa_assert(chip_rev);
2237
Jing Huang6a18b162010-10-18 17:08:54 -07002238 memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002239
2240 chip_rev[0] = 'R';
2241 chip_rev[1] = 'e';
2242 chip_rev[2] = 'v';
2243 chip_rev[3] = '-';
2244 chip_rev[4] = ioc->attr->asic_rev;
2245 chip_rev[5] = '\0';
2246}
2247
2248void
2249bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
2250{
Jing Huang6a18b162010-10-18 17:08:54 -07002251 memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
2252 memcpy(optrom_ver, ioc->attr->optrom_version,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002253 BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002254}
2255
2256void
2257bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
2258{
Jing Huang6a18b162010-10-18 17:08:54 -07002259 memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2260 memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002261}
2262
2263void
2264bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
2265{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002266 struct bfi_ioc_attr_s *ioc_attr;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002267
2268 bfa_assert(model);
Jing Huang6a18b162010-10-18 17:08:54 -07002269 memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002270
2271 ioc_attr = ioc->attr;
2272
Jing Huang5fbe25c2010-10-18 17:17:23 -07002273 /*
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002274 * model name
2275 */
Jing Huang6a18b162010-10-18 17:08:54 -07002276 snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002277 BFA_MFG_NAME, ioc_attr->card_type);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002278}
2279
2280enum bfa_ioc_state
2281bfa_ioc_get_state(struct bfa_ioc_s *ioc)
2282{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002283 enum bfa_iocpf_state iocpf_st;
2284 enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2285
2286 if (ioc_st == BFA_IOC_ENABLING ||
2287 ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2288
2289 iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2290
2291 switch (iocpf_st) {
2292 case BFA_IOCPF_SEMWAIT:
2293 ioc_st = BFA_IOC_SEMWAIT;
2294 break;
2295
2296 case BFA_IOCPF_HWINIT:
2297 ioc_st = BFA_IOC_HWINIT;
2298 break;
2299
2300 case BFA_IOCPF_FWMISMATCH:
2301 ioc_st = BFA_IOC_FWMISMATCH;
2302 break;
2303
2304 case BFA_IOCPF_FAIL:
2305 ioc_st = BFA_IOC_FAIL;
2306 break;
2307
2308 case BFA_IOCPF_INITFAIL:
2309 ioc_st = BFA_IOC_INITFAIL;
2310 break;
2311
2312 default:
2313 break;
2314 }
2315 }
2316
2317 return ioc_st;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002318}
2319
2320void
Jing Huang7725ccf2009-09-23 17:46:15 -07002321bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2322{
Jing Huang6a18b162010-10-18 17:08:54 -07002323 memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
Jing Huang7725ccf2009-09-23 17:46:15 -07002324
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002325 ioc_attr->state = bfa_ioc_get_state(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002326 ioc_attr->port_id = ioc->port_id;
2327
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002328 ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002329
2330 bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2331
2332 ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2333 ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002334 bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
Jing Huang7725ccf2009-09-23 17:46:15 -07002335}
2336
Jing Huang7725ccf2009-09-23 17:46:15 -07002337mac_t
2338bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2339{
Jing Huang15b64a82010-07-08 19:48:12 -07002340 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002341 * Check the IOC type and return the appropriate MAC
Jing Huang15b64a82010-07-08 19:48:12 -07002342 */
2343 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002344 return ioc->attr->fcoe_mac;
Jing Huang15b64a82010-07-08 19:48:12 -07002345 else
2346 return ioc->attr->mac;
2347}
2348
Jing Huang15b64a82010-07-08 19:48:12 -07002349mac_t
2350bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
2351{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002352 mac_t m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002353
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002354 m = ioc->attr->mfg_mac;
2355 if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
2356 m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2357 else
2358 bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
2359 bfa_ioc_pcifn(ioc));
Jing Huang7725ccf2009-09-23 17:46:15 -07002360
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002361 return m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002362}
2363
Jing Huang7725ccf2009-09-23 17:46:15 -07002364bfa_boolean_t
2365bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
2366{
Jing Huang293f82d2010-07-08 19:45:20 -07002367 return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id);
Jing Huang7725ccf2009-09-23 17:46:15 -07002368}
2369
Jing Huang5fbe25c2010-10-18 17:17:23 -07002370/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002371 * Retrieve saved firmware trace from a prior IOC failure.
2372 */
2373bfa_status_t
2374bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2375{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002376 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002377
2378 if (ioc->dbg_fwsave_len == 0)
2379 return BFA_STATUS_ENOFSAVE;
2380
2381 tlen = *trclen;
2382 if (tlen > ioc->dbg_fwsave_len)
2383 tlen = ioc->dbg_fwsave_len;
2384
Jing Huang6a18b162010-10-18 17:08:54 -07002385 memcpy(trcdata, ioc->dbg_fwsave, tlen);
Jing Huang7725ccf2009-09-23 17:46:15 -07002386 *trclen = tlen;
2387 return BFA_STATUS_OK;
2388}
2389
Krishna Gudipati738c9e62010-03-05 19:36:19 -08002390
Jing Huang5fbe25c2010-10-18 17:17:23 -07002391/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002392 * Retrieve saved firmware trace from a prior IOC failure.
2393 */
2394bfa_status_t
2395bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2396{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002397 u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2398 int tlen;
2399 bfa_status_t status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002400
2401 bfa_trc(ioc, *trclen);
2402
Jing Huang7725ccf2009-09-23 17:46:15 -07002403 tlen = *trclen;
2404 if (tlen > BFA_DBG_FWTRC_LEN)
2405 tlen = BFA_DBG_FWTRC_LEN;
Jing Huang7725ccf2009-09-23 17:46:15 -07002406
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002407 status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
2408 *trclen = tlen;
2409 return status;
2410}
Jing Huang7725ccf2009-09-23 17:46:15 -07002411
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002412static void
2413bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
2414{
2415 struct bfa_mbox_cmd_s cmd;
2416 struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002417
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002418 bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
2419 bfa_ioc_portid(ioc));
2420 req->ioc_class = ioc->ioc_mc;
2421 bfa_ioc_mbox_queue(ioc, &cmd);
2422}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002423
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002424static void
2425bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
2426{
2427 u32 fwsync_iter = 1000;
2428
2429 bfa_ioc_send_fwsync(ioc);
2430
Jing Huang5fbe25c2010-10-18 17:17:23 -07002431 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002432 * After sending a fw sync mbox command wait for it to
2433 * take effect. We will not wait for a response because
2434 * 1. fw_sync mbox cmd doesn't have a response.
2435 * 2. Even if we implement that, interrupts might not
2436 * be enabled when we call this function.
2437 * So, just keep checking if any mbox cmd is pending, and
2438 * after waiting for a reasonable amount of time, go ahead.
2439 * It is possible that fw has crashed and the mbox command
2440 * is never acknowledged.
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002441 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002442 while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
2443 fwsync_iter--;
2444}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002445
Jing Huang5fbe25c2010-10-18 17:17:23 -07002446/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002447 * Dump firmware smem
2448 */
2449bfa_status_t
2450bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
2451 u32 *offset, int *buflen)
2452{
2453 u32 loff;
2454 int dlen;
2455 bfa_status_t status;
2456 u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002457
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002458 if (*offset >= smem_len) {
2459 *offset = *buflen = 0;
2460 return BFA_STATUS_EINVAL;
2461 }
2462
2463 loff = *offset;
2464 dlen = *buflen;
2465
Jing Huang5fbe25c2010-10-18 17:17:23 -07002466 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002467 * First smem read, sync smem before proceeding
2468 * No need to sync before reading every chunk.
2469 */
2470 if (loff == 0)
2471 bfa_ioc_fwsync(ioc);
2472
2473 if ((loff + dlen) >= smem_len)
2474 dlen = smem_len - loff;
2475
2476 status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
2477
2478 if (status != BFA_STATUS_OK) {
2479 *offset = *buflen = 0;
2480 return status;
2481 }
2482
2483 *offset += dlen;
2484
2485 if (*offset >= smem_len)
2486 *offset = 0;
2487
2488 *buflen = dlen;
2489
2490 return status;
2491}
2492
Jing Huang5fbe25c2010-10-18 17:17:23 -07002493/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002494 * Firmware statistics
2495 */
2496bfa_status_t
2497bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
2498{
2499 u32 loff = BFI_IOC_FWSTATS_OFF + \
2500 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2501 int tlen;
2502 bfa_status_t status;
2503
2504 if (ioc->stats_busy) {
2505 bfa_trc(ioc, ioc->stats_busy);
2506 return BFA_STATUS_DEVBUSY;
2507 }
2508 ioc->stats_busy = BFA_TRUE;
2509
2510 tlen = sizeof(struct bfa_fw_stats_s);
2511 status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
2512
2513 ioc->stats_busy = BFA_FALSE;
2514 return status;
2515}
2516
2517bfa_status_t
2518bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2519{
2520 u32 loff = BFI_IOC_FWSTATS_OFF + \
2521 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2522 int tlen;
2523 bfa_status_t status;
2524
2525 if (ioc->stats_busy) {
2526 bfa_trc(ioc, ioc->stats_busy);
2527 return BFA_STATUS_DEVBUSY;
2528 }
2529 ioc->stats_busy = BFA_TRUE;
2530
2531 tlen = sizeof(struct bfa_fw_stats_s);
2532 status = bfa_ioc_smem_clr(ioc, loff, tlen);
2533
2534 ioc->stats_busy = BFA_FALSE;
2535 return status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002536}
2537
Jing Huang5fbe25c2010-10-18 17:17:23 -07002538/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002539 * Save firmware trace if configured.
2540 */
2541static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08002542bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -07002543{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002544 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002545
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08002546 if (ioc->dbg_fwsave_once) {
2547 ioc->dbg_fwsave_once = BFA_FALSE;
2548 if (ioc->dbg_fwsave_len) {
2549 tlen = ioc->dbg_fwsave_len;
2550 bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2551 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002552 }
2553}
2554
Jing Huang5fbe25c2010-10-18 17:17:23 -07002555/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002556 * Firmware failure detected. Start recovery actions.
2557 */
2558static void
2559bfa_ioc_recover(struct bfa_ioc_s *ioc)
2560{
Jing Huang7725ccf2009-09-23 17:46:15 -07002561 bfa_ioc_stats(ioc, ioc_hbfails);
2562 bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2563}
2564
Jing Huang7725ccf2009-09-23 17:46:15 -07002565static void
Jing Huang07b28382010-07-08 19:59:24 -07002566bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -07002567{
Jing Huang07b28382010-07-08 19:59:24 -07002568 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
2569 return;
Jing Huang7725ccf2009-09-23 17:46:15 -07002570}
2571
Jing Huang5fbe25c2010-10-18 17:17:23 -07002572/*
Maggie Zhangdf0f1932010-12-09 19:07:46 -08002573 * BFA IOC PF private functions
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002574 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002575static void
2576bfa_iocpf_timeout(void *ioc_arg)
2577{
2578 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2579
2580 bfa_trc(ioc, 0);
2581 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
2582}
2583
2584static void
2585bfa_iocpf_sem_timeout(void *ioc_arg)
2586{
2587 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2588
2589 bfa_ioc_hw_sem_get(ioc);
2590}
2591
Jing Huang5fbe25c2010-10-18 17:17:23 -07002592/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002593 * bfa timer function
2594 */
2595void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002596bfa_timer_beat(struct bfa_timer_mod_s *mod)
2597{
2598 struct list_head *qh = &mod->timer_q;
2599 struct list_head *qe, *qe_next;
2600 struct bfa_timer_s *elem;
2601 struct list_head timedout_q;
2602
2603 INIT_LIST_HEAD(&timedout_q);
2604
2605 qe = bfa_q_next(qh);
2606
2607 while (qe != qh) {
2608 qe_next = bfa_q_next(qe);
2609
2610 elem = (struct bfa_timer_s *) qe;
2611 if (elem->timeout <= BFA_TIMER_FREQ) {
2612 elem->timeout = 0;
2613 list_del(&elem->qe);
2614 list_add_tail(&elem->qe, &timedout_q);
2615 } else {
2616 elem->timeout -= BFA_TIMER_FREQ;
2617 }
2618
2619 qe = qe_next; /* go to next elem */
2620 }
2621
2622 /*
2623 * Pop all the timeout entries
2624 */
2625 while (!list_empty(&timedout_q)) {
2626 bfa_q_deq(&timedout_q, &elem);
2627 elem->timercb(elem->arg);
2628 }
2629}
2630
Jing Huang5fbe25c2010-10-18 17:17:23 -07002631/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002632 * Should be called with lock protection
2633 */
2634void
2635bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
2636 void (*timercb) (void *), void *arg, unsigned int timeout)
2637{
2638
2639 bfa_assert(timercb != NULL);
2640 bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
2641
2642 timer->timeout = timeout;
2643 timer->timercb = timercb;
2644 timer->arg = arg;
2645
2646 list_add_tail(&timer->qe, &mod->timer_q);
2647}
2648
Jing Huang5fbe25c2010-10-18 17:17:23 -07002649/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002650 * Should be called with lock protection
2651 */
2652void
2653bfa_timer_stop(struct bfa_timer_s *timer)
2654{
2655 bfa_assert(!list_empty(&timer->qe));
2656
2657 list_del(&timer->qe);
2658}