blob: a8f745420f3222e296a9e1d3cf04cc4ae70e84d2 [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
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070018#include "bfa_ioc.h"
19#include "bfi_ctreg.h"
20#include "bfa_defs.h"
21#include "bfa_defs_svc.h"
22#include "bfad_drv.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 Gudipatia36c61f2010-09-15 11:50:55 -070091static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -070092
Jing Huang7725ccf2009-09-23 17:46:15 -070093
Jing Huang5fbe25c2010-10-18 17:17:23 -070094/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070095 * IOC state machine definitions/declarations
Jing Huang7725ccf2009-09-23 17:46:15 -070096 */
97enum ioc_event {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070098 IOC_E_RESET = 1, /* IOC reset request */
99 IOC_E_ENABLE = 2, /* IOC enable request */
100 IOC_E_DISABLE = 3, /* IOC disable request */
101 IOC_E_DETACH = 4, /* driver detach cleanup */
102 IOC_E_ENABLED = 5, /* f/w enabled */
103 IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
104 IOC_E_DISABLED = 7, /* f/w disabled */
105 IOC_E_FAILED = 8, /* failure notice by iocpf sm */
106 IOC_E_HBFAIL = 9, /* heartbeat failure */
107 IOC_E_HWERROR = 10, /* hardware error interrupt */
108 IOC_E_TIMEOUT = 11, /* timeout */
Jing Huang7725ccf2009-09-23 17:46:15 -0700109};
110
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700111bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700112bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700113bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
114bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
115bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
116bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700117bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700118bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
119bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
120
121static struct bfa_sm_table_s ioc_sm_table[] = {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700122 {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
Jing Huang7725ccf2009-09-23 17:46:15 -0700123 {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700124 {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
Jing Huang7725ccf2009-09-23 17:46:15 -0700125 {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
126 {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
127 {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700128 {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
Jing Huang7725ccf2009-09-23 17:46:15 -0700129 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
130 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
131};
132
Jing Huang5fbe25c2010-10-18 17:17:23 -0700133/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700134 * IOCPF state machine definitions/declarations
135 */
136
137#define bfa_iocpf_timer_start(__ioc) \
138 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
139 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
140#define bfa_iocpf_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
141
142#define bfa_iocpf_recovery_timer_start(__ioc) \
143 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
144 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
145
146#define bfa_sem_timer_start(__ioc) \
147 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer, \
148 bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
149#define bfa_sem_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->sem_timer)
150
151/*
152 * Forward declareations for iocpf state machine
153 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700154static void bfa_iocpf_timeout(void *ioc_arg);
155static void bfa_iocpf_sem_timeout(void *ioc_arg);
156
Jing Huang5fbe25c2010-10-18 17:17:23 -0700157/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700158 * IOCPF state machine events
159 */
160enum iocpf_event {
161 IOCPF_E_ENABLE = 1, /* IOCPF enable request */
162 IOCPF_E_DISABLE = 2, /* IOCPF disable request */
163 IOCPF_E_STOP = 3, /* stop on driver detach */
164 IOCPF_E_FWREADY = 4, /* f/w initialization done */
165 IOCPF_E_FWRSP_ENABLE = 5, /* enable f/w response */
166 IOCPF_E_FWRSP_DISABLE = 6, /* disable f/w response */
167 IOCPF_E_FAIL = 7, /* failure notice by ioc sm */
168 IOCPF_E_INITFAIL = 8, /* init fail notice by ioc sm */
169 IOCPF_E_GETATTRFAIL = 9, /* init fail notice by ioc sm */
170 IOCPF_E_SEMLOCKED = 10, /* h/w semaphore is locked */
171 IOCPF_E_TIMEOUT = 11, /* f/w response timeout */
172};
173
Jing Huang5fbe25c2010-10-18 17:17:23 -0700174/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700175 * IOCPF states
176 */
177enum bfa_iocpf_state {
178 BFA_IOCPF_RESET = 1, /* IOC is in reset state */
179 BFA_IOCPF_SEMWAIT = 2, /* Waiting for IOC h/w semaphore */
180 BFA_IOCPF_HWINIT = 3, /* IOC h/w is being initialized */
181 BFA_IOCPF_READY = 4, /* IOCPF is initialized */
182 BFA_IOCPF_INITFAIL = 5, /* IOCPF failed */
183 BFA_IOCPF_FAIL = 6, /* IOCPF failed */
184 BFA_IOCPF_DISABLING = 7, /* IOCPF is being disabled */
185 BFA_IOCPF_DISABLED = 8, /* IOCPF is disabled */
186 BFA_IOCPF_FWMISMATCH = 9, /* IOC f/w different from drivers */
187};
188
189bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
190bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
191bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
192bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
193bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
194bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
195bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
196bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
197bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
198bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
199bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
200
201static struct bfa_sm_table_s iocpf_sm_table[] = {
202 {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
203 {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
204 {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
205 {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
206 {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
207 {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
208 {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
209 {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
210 {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
211 {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
212 {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
213};
214
Jing Huang5fbe25c2010-10-18 17:17:23 -0700215/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700216 * IOC State Machine
217 */
218
Jing Huang5fbe25c2010-10-18 17:17:23 -0700219/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700220 * Beginning state. IOC uninit state.
221 */
222
223static void
224bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
225{
226}
227
Jing Huang5fbe25c2010-10-18 17:17:23 -0700228/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700229 * IOC is in uninit state.
230 */
231static void
232bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
233{
234 bfa_trc(ioc, event);
235
236 switch (event) {
237 case IOC_E_RESET:
238 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
239 break;
240
241 default:
242 bfa_sm_fault(ioc, event);
243 }
244}
Jing Huang5fbe25c2010-10-18 17:17:23 -0700245/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700246 * Reset entry actions -- initialize state machine
247 */
248static void
249bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
250{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700251 bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
Jing Huang7725ccf2009-09-23 17:46:15 -0700252}
253
Jing Huang5fbe25c2010-10-18 17:17:23 -0700254/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700255 * IOC is in reset state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700256 */
257static void
258bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
259{
260 bfa_trc(ioc, event);
261
262 switch (event) {
263 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700264 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
265 break;
266
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700267 case IOC_E_DISABLE:
268 bfa_ioc_disable_comp(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700269 break;
270
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700271 case IOC_E_DETACH:
272 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700273 break;
274
275 default:
276 bfa_sm_fault(ioc, event);
277 }
278}
279
280
281static void
282bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
283{
Maggie Zhangf7f738122010-12-09 19:08:43 -0800284 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700285}
286
Jing Huang5fbe25c2010-10-18 17:17:23 -0700287/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700288 * Host IOC function is being enabled, awaiting response from firmware.
289 * Semaphore is acquired.
290 */
291static void
292bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
293{
294 bfa_trc(ioc, event);
295
296 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700297 case IOC_E_ENABLED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700298 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
299 break;
300
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700301 case IOC_E_FAILED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700302 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
303 break;
304
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700305 case IOC_E_HWERROR:
306 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800307 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700308 break;
309
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700310 case IOC_E_DISABLE:
311 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
312 break;
313
314 case IOC_E_DETACH:
315 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800316 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700317 break;
318
319 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700320 break;
321
322 default:
323 bfa_sm_fault(ioc, event);
324 }
325}
326
327
328static void
329bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
330{
331 bfa_ioc_timer_start(ioc);
332 bfa_ioc_send_getattr(ioc);
333}
334
Jing Huang5fbe25c2010-10-18 17:17:23 -0700335/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700336 * IOC configuration in progress. Timer is active.
337 */
338static void
339bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
340{
341 bfa_trc(ioc, event);
342
343 switch (event) {
344 case IOC_E_FWRSP_GETATTR:
345 bfa_ioc_timer_stop(ioc);
Jing Huang07b28382010-07-08 19:59:24 -0700346 bfa_ioc_check_attr_wwns(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700347 bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
348 break;
349
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700350 case IOC_E_FAILED:
351 bfa_ioc_timer_stop(ioc);
352 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
353 break;
354
Jing Huang7725ccf2009-09-23 17:46:15 -0700355 case IOC_E_HWERROR:
356 bfa_ioc_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700357 /* fall through */
Jing Huang7725ccf2009-09-23 17:46:15 -0700358
359 case IOC_E_TIMEOUT:
360 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800361 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 Zhangf7f738122010-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 Gudipatia36c61f2010-09-15 11:50:55 -0700402 case IOC_E_FAILED:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800403 bfa_hb_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700404 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
405 break;
406
407 case IOC_E_HWERROR:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800408 bfa_hb_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700409 /* !!! fall through !!! */
Jing Huang7725ccf2009-09-23 17:46:15 -0700410
411 case IOC_E_HBFAIL:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700412 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800413 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700414 break;
415
416 default:
417 bfa_sm_fault(ioc, event);
418 }
419}
420
421
422static void
423bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
424{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700425 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Maggie Zhangf7f738122010-12-09 19:08:43 -0800426 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
Jing Huang88166242010-12-09 17:11:53 -0800427 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700428}
429
Jing Huang5fbe25c2010-10-18 17:17:23 -0700430/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700431 * IOC is being disabled
432 */
433static void
434bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
435{
436 bfa_trc(ioc, event);
437
438 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700439 case IOC_E_DISABLED:
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800440 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
441 break;
442
443 case IOC_E_HWERROR:
Jing Huang7725ccf2009-09-23 17:46:15 -0700444 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700445 * No state change. Will move to disabled state
446 * after iocpf sm completes failure processing and
447 * moves to disabled state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700448 */
Maggie Zhangf7f738122010-12-09 19:08:43 -0800449 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700450 break;
451
452 default:
453 bfa_sm_fault(ioc, event);
454 }
455}
456
Jing Huang5fbe25c2010-10-18 17:17:23 -0700457/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700458 * IOC disable completion entry.
459 */
460static void
461bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
462{
463 bfa_ioc_disable_comp(ioc);
464}
465
466static void
467bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
468{
469 bfa_trc(ioc, event);
470
471 switch (event) {
472 case IOC_E_ENABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700473 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700474 break;
475
476 case IOC_E_DISABLE:
477 ioc->cbfn->disable_cbfn(ioc->bfa);
478 break;
479
Jing Huang7725ccf2009-09-23 17:46:15 -0700480 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700481 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800482 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700483 break;
484
485 default:
486 bfa_sm_fault(ioc, event);
487 }
488}
489
490
491static void
492bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
493{
494 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700495}
496
Jing Huang5fbe25c2010-10-18 17:17:23 -0700497/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700498 * Hardware initialization failed.
499 */
500static void
501bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
502{
503 bfa_trc(ioc, event);
504
505 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700506 case IOC_E_ENABLED:
507 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
508 break;
509
510 case IOC_E_FAILED:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700511 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700512 * Initialization failure during iocpf init retry.
513 */
514 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
515 break;
516
Jing Huang7725ccf2009-09-23 17:46:15 -0700517 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700518 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700519 break;
520
521 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700522 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800523 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700524 break;
525
526 default:
527 bfa_sm_fault(ioc, event);
528 }
529}
530
531
532static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700533bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -0700534{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700535 struct list_head *qe;
536 struct bfa_ioc_hbfail_notify_s *notify;
537 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Jing Huang7725ccf2009-09-23 17:46:15 -0700538
Jing Huang5fbe25c2010-10-18 17:17:23 -0700539 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700540 * Notify driver and common modules registered for notification.
541 */
542 ioc->cbfn->hbfail_cbfn(ioc->bfa);
543 list_for_each(qe, &ioc->hb_notify_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700544 notify = (struct bfa_ioc_hbfail_notify_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700545 notify->cbfn(notify->cbarg);
546 }
547
Jing Huang88166242010-12-09 17:11:53 -0800548 BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700549 "Heart Beat of IOC has failed\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700550}
551
Jing Huang5fbe25c2010-10-18 17:17:23 -0700552/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700553 * IOC failure.
Jing Huang7725ccf2009-09-23 17:46:15 -0700554 */
555static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700556bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700557{
558 bfa_trc(ioc, event);
559
560 switch (event) {
561
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700562 case IOC_E_FAILED:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700563 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700564 * Initialization failure during iocpf recovery.
565 * !!! Fall through !!!
566 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700567 case IOC_E_ENABLE:
568 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
569 break;
570
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700571 case IOC_E_ENABLED:
572 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
573 break;
574
Jing Huang7725ccf2009-09-23 17:46:15 -0700575 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700576 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700577 break;
578
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800579 case IOC_E_HWERROR:
580 /*
581 * HB failure notification, ignore.
582 */
583 break;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700584 default:
585 bfa_sm_fault(ioc, event);
586 }
587}
588
589
590
Jing Huang5fbe25c2010-10-18 17:17:23 -0700591/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700592 * IOCPF State Machine
593 */
594
595
Jing Huang5fbe25c2010-10-18 17:17:23 -0700596/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700597 * Reset entry actions -- initialize state machine
598 */
599static void
600bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
601{
602 iocpf->retry_count = 0;
603 iocpf->auto_recover = bfa_auto_recover;
604}
605
Jing Huang5fbe25c2010-10-18 17:17:23 -0700606/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700607 * Beginning state. IOC is in reset state.
608 */
609static void
610bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
611{
612 struct bfa_ioc_s *ioc = iocpf->ioc;
613
614 bfa_trc(ioc, event);
615
616 switch (event) {
617 case IOCPF_E_ENABLE:
618 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
619 break;
620
621 case IOCPF_E_STOP:
622 break;
623
624 default:
625 bfa_sm_fault(ioc, event);
626 }
627}
628
Jing Huang5fbe25c2010-10-18 17:17:23 -0700629/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700630 * Semaphore should be acquired for version check.
631 */
632static void
633bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
634{
635 bfa_ioc_hw_sem_get(iocpf->ioc);
636}
637
Jing Huang5fbe25c2010-10-18 17:17:23 -0700638/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700639 * Awaiting h/w semaphore to continue with version check.
640 */
641static void
642bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
643{
644 struct bfa_ioc_s *ioc = iocpf->ioc;
645
646 bfa_trc(ioc, event);
647
648 switch (event) {
649 case IOCPF_E_SEMLOCKED:
650 if (bfa_ioc_firmware_lock(ioc)) {
651 iocpf->retry_count = 0;
652 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
653 } else {
Maggie Zhangf7f738122010-12-09 19:08:43 -0800654 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700655 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
656 }
657 break;
658
659 case IOCPF_E_DISABLE:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800660 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700661 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800662 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700663 break;
664
665 case IOCPF_E_STOP:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800666 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700667 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
668 break;
669
670 default:
671 bfa_sm_fault(ioc, event);
672 }
673}
674
Jing Huang5fbe25c2010-10-18 17:17:23 -0700675/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700676 * Notify enable completion callback.
677 */
678static void
679bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
680{
681 /*
682 * Call only the first time sm enters fwmismatch state.
683 */
684 if (iocpf->retry_count == 0)
685 bfa_ioc_pf_fwmismatch(iocpf->ioc);
686
687 iocpf->retry_count++;
688 bfa_iocpf_timer_start(iocpf->ioc);
689}
690
Jing Huang5fbe25c2010-10-18 17:17:23 -0700691/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700692 * Awaiting firmware version match.
693 */
694static void
695bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
696{
697 struct bfa_ioc_s *ioc = iocpf->ioc;
698
699 bfa_trc(ioc, event);
700
701 switch (event) {
702 case IOCPF_E_TIMEOUT:
703 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
704 break;
705
706 case IOCPF_E_DISABLE:
707 bfa_iocpf_timer_stop(ioc);
708 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800709 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700710 break;
711
712 case IOCPF_E_STOP:
713 bfa_iocpf_timer_stop(ioc);
714 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
715 break;
716
717 default:
718 bfa_sm_fault(ioc, event);
719 }
720}
721
Jing Huang5fbe25c2010-10-18 17:17:23 -0700722/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700723 * Request for semaphore.
724 */
725static void
726bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
727{
728 bfa_ioc_hw_sem_get(iocpf->ioc);
729}
730
Jing Huang5fbe25c2010-10-18 17:17:23 -0700731/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700732 * Awaiting semaphore for h/w initialzation.
733 */
734static void
735bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
736{
737 struct bfa_ioc_s *ioc = iocpf->ioc;
738
739 bfa_trc(ioc, event);
740
741 switch (event) {
742 case IOCPF_E_SEMLOCKED:
743 iocpf->retry_count = 0;
744 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
745 break;
746
747 case IOCPF_E_DISABLE:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800748 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700749 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
750 break;
751
752 default:
753 bfa_sm_fault(ioc, event);
754 }
755}
756
757
758static void
759bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
760{
761 bfa_iocpf_timer_start(iocpf->ioc);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800762 bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700763}
764
Jing Huang5fbe25c2010-10-18 17:17:23 -0700765/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700766 * Hardware is being initialized. Interrupts are enabled.
767 * Holding hardware semaphore lock.
768 */
769static void
770bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
771{
772 struct bfa_ioc_s *ioc = iocpf->ioc;
773
774 bfa_trc(ioc, event);
775
776 switch (event) {
777 case IOCPF_E_FWREADY:
778 bfa_iocpf_timer_stop(ioc);
779 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
780 break;
781
782 case IOCPF_E_INITFAIL:
783 bfa_iocpf_timer_stop(ioc);
784 /*
785 * !!! fall through !!!
786 */
787
788 case IOCPF_E_TIMEOUT:
789 iocpf->retry_count++;
790 if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
791 bfa_iocpf_timer_start(ioc);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800792 bfa_ioc_hwinit(ioc, BFA_TRUE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700793 break;
794 }
795
Maggie Zhangf7f738122010-12-09 19:08:43 -0800796 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700797 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
798
799 if (event == IOCPF_E_TIMEOUT)
Maggie Zhangf7f738122010-12-09 19:08:43 -0800800 bfa_fsm_send_event(ioc, IOC_E_FAILED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700801 break;
802
803 case IOCPF_E_DISABLE:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800804 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700805 bfa_iocpf_timer_stop(ioc);
806 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
807 break;
808
809 default:
810 bfa_sm_fault(ioc, event);
811 }
812}
813
814
815static void
816bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
817{
818 bfa_iocpf_timer_start(iocpf->ioc);
819 bfa_ioc_send_enable(iocpf->ioc);
820}
821
Jing Huang5fbe25c2010-10-18 17:17:23 -0700822/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700823 * Host IOC function is being enabled, awaiting response from firmware.
824 * Semaphore is acquired.
825 */
826static void
827bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
828{
829 struct bfa_ioc_s *ioc = iocpf->ioc;
830
831 bfa_trc(ioc, event);
832
833 switch (event) {
834 case IOCPF_E_FWRSP_ENABLE:
835 bfa_iocpf_timer_stop(ioc);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800836 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700837 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
838 break;
839
840 case IOCPF_E_INITFAIL:
841 bfa_iocpf_timer_stop(ioc);
842 /*
843 * !!! fall through !!!
844 */
845
846 case IOCPF_E_TIMEOUT:
847 iocpf->retry_count++;
848 if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
Jing Huang53440262010-10-18 17:12:29 -0700849 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700850 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
851 break;
852 }
853
Maggie Zhangf7f738122010-12-09 19:08:43 -0800854 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700855 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
856
857 if (event == IOCPF_E_TIMEOUT)
Maggie Zhangf7f738122010-12-09 19:08:43 -0800858 bfa_fsm_send_event(ioc, IOC_E_FAILED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700859 break;
860
861 case IOCPF_E_DISABLE:
862 bfa_iocpf_timer_stop(ioc);
Maggie Zhangf7f738122010-12-09 19:08:43 -0800863 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700864 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
865 break;
866
867 case IOCPF_E_FWREADY:
868 bfa_ioc_send_enable(ioc);
869 break;
870
871 default:
872 bfa_sm_fault(ioc, event);
873 }
874}
875
876
877
878static void
879bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
880{
Maggie Zhangf7f738122010-12-09 19:08:43 -0800881 bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700882}
883
884static void
885bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
886{
887 struct bfa_ioc_s *ioc = iocpf->ioc;
888
889 bfa_trc(ioc, event);
890
891 switch (event) {
892 case IOCPF_E_DISABLE:
893 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
894 break;
895
896 case IOCPF_E_GETATTRFAIL:
897 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
898 break;
899
900 case IOCPF_E_FAIL:
901 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
902 break;
903
904 case IOCPF_E_FWREADY:
Maggie Zhangf7f738122010-12-09 19:08:43 -0800905 if (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700906 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
907 else
908 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
909
Maggie Zhangf7f738122010-12-09 19:08:43 -0800910 bfa_fsm_send_event(ioc, IOC_E_FAILED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700911 break;
912
913 default:
914 bfa_sm_fault(ioc, event);
915 }
916}
917
918
919static void
920bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
921{
922 bfa_iocpf_timer_start(iocpf->ioc);
923 bfa_ioc_send_disable(iocpf->ioc);
924}
925
Jing Huang5fbe25c2010-10-18 17:17:23 -0700926/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700927 * IOC is being disabled
928 */
929static void
930bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
931{
932 struct bfa_ioc_s *ioc = iocpf->ioc;
933
934 bfa_trc(ioc, event);
935
936 switch (event) {
937 case IOCPF_E_FWRSP_DISABLE:
938 case IOCPF_E_FWREADY:
939 bfa_iocpf_timer_stop(ioc);
940 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
941 break;
942
943 case IOCPF_E_FAIL:
944 bfa_iocpf_timer_stop(ioc);
945 /*
946 * !!! fall through !!!
947 */
948
949 case IOCPF_E_TIMEOUT:
Jing Huang53440262010-10-18 17:12:29 -0700950 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700951 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
952 break;
953
954 case IOCPF_E_FWRSP_ENABLE:
955 break;
956
957 default:
958 bfa_sm_fault(ioc, event);
959 }
960}
961
Jing Huang5fbe25c2010-10-18 17:17:23 -0700962/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700963 * IOC disable completion entry.
964 */
965static void
966bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
967{
Maggie Zhangf7f738122010-12-09 19:08:43 -0800968 bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700969}
970
971static void
972bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
973{
974 struct bfa_ioc_s *ioc = iocpf->ioc;
975
976 bfa_trc(ioc, event);
977
978 switch (event) {
979 case IOCPF_E_ENABLE:
980 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
981 break;
982
983 case IOCPF_E_STOP:
984 bfa_ioc_firmware_unlock(ioc);
985 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
986 break;
987
988 default:
989 bfa_sm_fault(ioc, event);
990 }
991}
992
993
994static void
995bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
996{
997 bfa_iocpf_timer_start(iocpf->ioc);
998}
999
Jing Huang5fbe25c2010-10-18 17:17:23 -07001000/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001001 * Hardware initialization failed.
1002 */
1003static void
1004bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1005{
1006 struct bfa_ioc_s *ioc = iocpf->ioc;
1007
1008 bfa_trc(ioc, event);
1009
1010 switch (event) {
1011 case IOCPF_E_DISABLE:
1012 bfa_iocpf_timer_stop(ioc);
1013 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1014 break;
1015
1016 case IOCPF_E_STOP:
1017 bfa_iocpf_timer_stop(ioc);
1018 bfa_ioc_firmware_unlock(ioc);
1019 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1020 break;
1021
1022 case IOCPF_E_TIMEOUT:
1023 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1024 break;
1025
1026 default:
1027 bfa_sm_fault(ioc, event);
1028 }
1029}
1030
1031
1032static void
1033bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
1034{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001035 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001036 * Mark IOC as failed in hardware and stop firmware.
1037 */
1038 bfa_ioc_lpu_stop(iocpf->ioc);
Jing Huang53440262010-10-18 17:12:29 -07001039 writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001040
Jing Huang5fbe25c2010-10-18 17:17:23 -07001041 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001042 * Notify other functions on HB failure.
1043 */
1044 bfa_ioc_notify_hbfail(iocpf->ioc);
1045
Jing Huang5fbe25c2010-10-18 17:17:23 -07001046 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001047 * Flush any queued up mailbox requests.
1048 */
1049 bfa_ioc_mbox_hbfail(iocpf->ioc);
1050
1051 if (iocpf->auto_recover)
1052 bfa_iocpf_recovery_timer_start(iocpf->ioc);
1053}
1054
Jing Huang5fbe25c2010-10-18 17:17:23 -07001055/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001056 * IOC is in failed state.
1057 */
1058static void
1059bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1060{
1061 struct bfa_ioc_s *ioc = iocpf->ioc;
1062
1063 bfa_trc(ioc, event);
1064
1065 switch (event) {
1066 case IOCPF_E_DISABLE:
1067 if (iocpf->auto_recover)
1068 bfa_iocpf_timer_stop(ioc);
1069 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1070 break;
1071
1072 case IOCPF_E_TIMEOUT:
1073 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1074 break;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001075
Jing Huang7725ccf2009-09-23 17:46:15 -07001076 default:
1077 bfa_sm_fault(ioc, event);
1078 }
1079}
1080
1081
1082
Jing Huang5fbe25c2010-10-18 17:17:23 -07001083/*
Maggie Zhangdf0f1932010-12-09 19:07:46 -08001084 * BFA IOC private functions
Jing Huang7725ccf2009-09-23 17:46:15 -07001085 */
1086
1087static void
1088bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
1089{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001090 struct list_head *qe;
1091 struct bfa_ioc_hbfail_notify_s *notify;
Jing Huang7725ccf2009-09-23 17:46:15 -07001092
1093 ioc->cbfn->disable_cbfn(ioc->bfa);
1094
Jing Huang5fbe25c2010-10-18 17:17:23 -07001095 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001096 * Notify common modules registered for notification.
1097 */
1098 list_for_each(qe, &ioc->hb_notify_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001099 notify = (struct bfa_ioc_hbfail_notify_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -07001100 notify->cbfn(notify->cbarg);
1101 }
1102}
1103
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001104bfa_boolean_t
Jing Huang53440262010-10-18 17:12:29 -07001105bfa_ioc_sem_get(void __iomem *sem_reg)
Jing Huang7725ccf2009-09-23 17:46:15 -07001106{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001107 u32 r32;
1108 int cnt = 0;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001109#define BFA_SEM_SPINCNT 3000
Jing Huang7725ccf2009-09-23 17:46:15 -07001110
Jing Huang53440262010-10-18 17:12:29 -07001111 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001112
1113 while (r32 && (cnt < BFA_SEM_SPINCNT)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001114 cnt++;
Jing Huang6a18b162010-10-18 17:08:54 -07001115 udelay(2);
Jing Huang53440262010-10-18 17:12:29 -07001116 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001117 }
1118
1119 if (r32 == 0)
1120 return BFA_TRUE;
1121
Jing Huang7725ccf2009-09-23 17:46:15 -07001122 bfa_assert(cnt < BFA_SEM_SPINCNT);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001123 return BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001124}
1125
Jing Huang7725ccf2009-09-23 17:46:15 -07001126
1127static void
1128bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
1129{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001130 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001131
Jing Huang5fbe25c2010-10-18 17:17:23 -07001132 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001133 * First read to the semaphore register will return 0, subsequent reads
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001134 * will return 1. Semaphore is released by writing 1 to the register
Jing Huang7725ccf2009-09-23 17:46:15 -07001135 */
Jing Huang53440262010-10-18 17:12:29 -07001136 r32 = readl(ioc->ioc_regs.ioc_sem_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001137 if (r32 == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001138 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
Jing Huang7725ccf2009-09-23 17:46:15 -07001139 return;
1140 }
1141
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001142 bfa_sem_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001143}
1144
Jing Huang5fbe25c2010-10-18 17:17:23 -07001145/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001146 * Initialize LPU local memory (aka secondary memory / SRAM)
1147 */
1148static void
1149bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
1150{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001151 u32 pss_ctl;
1152 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001153#define PSS_LMEM_INIT_TIME 10000
1154
Jing Huang53440262010-10-18 17:12:29 -07001155 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001156 pss_ctl &= ~__PSS_LMEM_RESET;
1157 pss_ctl |= __PSS_LMEM_INIT_EN;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001158
1159 /*
1160 * i2c workaround 12.5khz clock
1161 */
1162 pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
Jing Huang53440262010-10-18 17:12:29 -07001163 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001164
Jing Huang5fbe25c2010-10-18 17:17:23 -07001165 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001166 * wait for memory initialization to be complete
1167 */
1168 i = 0;
1169 do {
Jing Huang53440262010-10-18 17:12:29 -07001170 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001171 i++;
1172 } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1173
Jing Huang5fbe25c2010-10-18 17:17:23 -07001174 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001175 * If memory initialization is not successful, IOC timeout will catch
1176 * such failures.
1177 */
1178 bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
1179 bfa_trc(ioc, pss_ctl);
1180
1181 pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
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
1185static void
1186bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
1187{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001188 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001189
Jing Huang5fbe25c2010-10-18 17:17:23 -07001190 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001191 * Take processor out of reset.
1192 */
Jing Huang53440262010-10-18 17:12:29 -07001193 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001194 pss_ctl &= ~__PSS_LPU0_RESET;
1195
Jing Huang53440262010-10-18 17:12:29 -07001196 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001197}
1198
1199static void
1200bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
1201{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001202 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001203
Jing Huang5fbe25c2010-10-18 17:17:23 -07001204 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001205 * Put processors in reset.
1206 */
Jing Huang53440262010-10-18 17:12:29 -07001207 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001208 pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1209
Jing Huang53440262010-10-18 17:12:29 -07001210 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001211}
1212
Jing Huang5fbe25c2010-10-18 17:17:23 -07001213/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001214 * Get driver and firmware versions.
1215 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001216void
Jing Huang7725ccf2009-09-23 17:46:15 -07001217bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1218{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001219 u32 pgnum, pgoff;
1220 u32 loff = 0;
1221 int i;
1222 u32 *fwsig = (u32 *) fwhdr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001223
Maggie Zhangf7f738122010-12-09 19:08:43 -08001224 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1225 pgoff = PSS_SMEM_PGOFF(loff);
Jing Huang53440262010-10-18 17:12:29 -07001226 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001227
1228 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
1229 i++) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001230 fwsig[i] =
1231 bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001232 loff += sizeof(u32);
1233 }
1234}
1235
Jing Huang5fbe25c2010-10-18 17:17:23 -07001236/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001237 * Returns TRUE if same.
1238 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001239bfa_boolean_t
Jing Huang7725ccf2009-09-23 17:46:15 -07001240bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1241{
1242 struct bfi_ioc_image_hdr_s *drv_fwhdr;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001243 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001244
Jing Huang293f82d2010-07-08 19:45:20 -07001245 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001246 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001247
1248 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1249 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
1250 bfa_trc(ioc, i);
1251 bfa_trc(ioc, fwhdr->md5sum[i]);
1252 bfa_trc(ioc, drv_fwhdr->md5sum[i]);
1253 return BFA_FALSE;
1254 }
1255 }
1256
1257 bfa_trc(ioc, fwhdr->md5sum[0]);
1258 return BFA_TRUE;
1259}
1260
Jing Huang5fbe25c2010-10-18 17:17:23 -07001261/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001262 * Return true if current running version is valid. Firmware signature and
1263 * execution context (driver/bios) must match.
1264 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001265static bfa_boolean_t
1266bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001267{
1268 struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
1269
Jing Huang5fbe25c2010-10-18 17:17:23 -07001270 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001271 * If bios/efi boot (flash based) -- return true
1272 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001273 if (bfa_ioc_is_bios_optrom(ioc))
Jing Huang7725ccf2009-09-23 17:46:15 -07001274 return BFA_TRUE;
1275
1276 bfa_ioc_fwver_get(ioc, &fwhdr);
Jing Huang293f82d2010-07-08 19:45:20 -07001277 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001278 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001279
1280 if (fwhdr.signature != drv_fwhdr->signature) {
1281 bfa_trc(ioc, fwhdr.signature);
1282 bfa_trc(ioc, drv_fwhdr->signature);
1283 return BFA_FALSE;
1284 }
1285
Jing Huang53440262010-10-18 17:12:29 -07001286 if (swab32(fwhdr.param) != boot_env) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001287 bfa_trc(ioc, fwhdr.param);
1288 bfa_trc(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001289 return BFA_FALSE;
1290 }
1291
1292 return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1293}
1294
Jing Huang5fbe25c2010-10-18 17:17:23 -07001295/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001296 * Conditionally flush any pending message from firmware at start.
1297 */
1298static void
1299bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1300{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001301 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001302
Jing Huang53440262010-10-18 17:12:29 -07001303 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001304 if (r32)
Jing Huang53440262010-10-18 17:12:29 -07001305 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001306}
1307
1308
1309static void
1310bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1311{
1312 enum bfi_ioc_state ioc_fwstate;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001313 bfa_boolean_t fwvalid;
1314 u32 boot_type;
1315 u32 boot_env;
Jing Huang7725ccf2009-09-23 17:46:15 -07001316
Jing Huang53440262010-10-18 17:12:29 -07001317 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07001318
1319 if (force)
1320 ioc_fwstate = BFI_IOC_UNINIT;
1321
1322 bfa_trc(ioc, ioc_fwstate);
1323
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001324 boot_type = BFI_BOOT_TYPE_NORMAL;
1325 boot_env = BFI_BOOT_LOADER_OS;
1326
Jing Huang5fbe25c2010-10-18 17:17:23 -07001327 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001328 * Flash based firmware boot BIOS env.
1329 */
1330 if (bfa_ioc_is_bios_optrom(ioc)) {
1331 boot_type = BFI_BOOT_TYPE_FLASH;
1332 boot_env = BFI_BOOT_LOADER_BIOS;
1333 }
1334
Jing Huang5fbe25c2010-10-18 17:17:23 -07001335 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001336 * Flash based firmware boot UEFI env.
1337 */
1338 if (bfa_ioc_is_uefi(ioc)) {
1339 boot_type = BFI_BOOT_TYPE_FLASH;
1340 boot_env = BFI_BOOT_LOADER_UEFI;
1341 }
1342
Jing Huang5fbe25c2010-10-18 17:17:23 -07001343 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001344 * check if firmware is valid
1345 */
1346 fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001347 BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001348
1349 if (!fwvalid) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001350 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001351 return;
1352 }
1353
Jing Huang5fbe25c2010-10-18 17:17:23 -07001354 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001355 * If hardware initialization is in progress (initialized by other IOC),
1356 * just wait for an initialization completion interrupt.
1357 */
1358 if (ioc_fwstate == BFI_IOC_INITING) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001359 ioc->cbfn->reset_cbfn(ioc->bfa);
1360 return;
1361 }
1362
Jing Huang5fbe25c2010-10-18 17:17:23 -07001363 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001364 * If IOC function is disabled and firmware version is same,
1365 * just re-enable IOC.
Jing Huang07b28382010-07-08 19:59:24 -07001366 *
1367 * If option rom, IOC must not be in operational state. With
1368 * convergence, IOC will be in operational state when 2nd driver
1369 * is loaded.
Jing Huang7725ccf2009-09-23 17:46:15 -07001370 */
Jing Huang07b28382010-07-08 19:59:24 -07001371 if (ioc_fwstate == BFI_IOC_DISABLED ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001372 (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001373
Jing Huang5fbe25c2010-10-18 17:17:23 -07001374 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001375 * When using MSI-X any pending firmware ready event should
1376 * be flushed. Otherwise MSI-X interrupts are not delivered.
1377 */
1378 bfa_ioc_msgflush(ioc);
1379 ioc->cbfn->reset_cbfn(ioc->bfa);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001380 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001381 return;
1382 }
1383
Jing Huang5fbe25c2010-10-18 17:17:23 -07001384 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001385 * Initialize the h/w for any other states.
1386 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001387 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001388}
1389
1390static void
1391bfa_ioc_timeout(void *ioc_arg)
1392{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001393 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -07001394
1395 bfa_trc(ioc, 0);
1396 bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1397}
1398
1399void
1400bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1401{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001402 u32 *msgp = (u32 *) ioc_msg;
1403 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001404
1405 bfa_trc(ioc, msgp[0]);
1406 bfa_trc(ioc, len);
1407
1408 bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
1409
1410 /*
1411 * first write msg to mailbox registers
1412 */
1413 for (i = 0; i < len / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001414 writel(cpu_to_le32(msgp[i]),
1415 ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001416
1417 for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001418 writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001419
1420 /*
1421 * write 1 to mailbox CMD to trigger LPU event
1422 */
Jing Huang53440262010-10-18 17:12:29 -07001423 writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1424 (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001425}
1426
1427static void
1428bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1429{
1430 struct bfi_ioc_ctrl_req_s enable_req;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001431 struct bfa_timeval_s tv;
Jing Huang7725ccf2009-09-23 17:46:15 -07001432
1433 bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1434 bfa_ioc_portid(ioc));
1435 enable_req.ioc_class = ioc->ioc_mc;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001436 bfa_os_gettimeofday(&tv);
Jing Huangba816ea2010-10-18 17:10:50 -07001437 enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
Jing Huang7725ccf2009-09-23 17:46:15 -07001438 bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1439}
1440
1441static void
1442bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1443{
1444 struct bfi_ioc_ctrl_req_s disable_req;
1445
1446 bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1447 bfa_ioc_portid(ioc));
1448 bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1449}
1450
1451static void
1452bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1453{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001454 struct bfi_ioc_getattr_req_s attr_req;
Jing Huang7725ccf2009-09-23 17:46:15 -07001455
1456 bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1457 bfa_ioc_portid(ioc));
1458 bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1459 bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1460}
1461
1462static void
1463bfa_ioc_hb_check(void *cbarg)
1464{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001465 struct bfa_ioc_s *ioc = cbarg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001466 u32 hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001467
Jing Huang53440262010-10-18 17:12:29 -07001468 hb_count = readl(ioc->ioc_regs.heartbeat);
Jing Huang7725ccf2009-09-23 17:46:15 -07001469 if (ioc->hb_count == hb_count) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001470 printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
Jing Huang7725ccf2009-09-23 17:46:15 -07001471 bfa_ioc_recover(ioc);
1472 return;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001473 } else {
1474 ioc->hb_count = hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001475 }
1476
1477 bfa_ioc_mbox_poll(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001478 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001479}
1480
1481static void
1482bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1483{
Jing Huang53440262010-10-18 17:12:29 -07001484 ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001485 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001486}
1487
Jing Huang5fbe25c2010-10-18 17:17:23 -07001488/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001489 * Initiate a full firmware download.
Jing Huang7725ccf2009-09-23 17:46:15 -07001490 */
1491static void
1492bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001493 u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001494{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001495 u32 *fwimg;
1496 u32 pgnum, pgoff;
1497 u32 loff = 0;
1498 u32 chunkno = 0;
1499 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001500
Jing Huang5fbe25c2010-10-18 17:17:23 -07001501 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001502 * Initialize LMEM first before code download
1503 */
1504 bfa_ioc_lmem_init(ioc);
1505
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001506 bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
1507 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
Jing Huang7725ccf2009-09-23 17:46:15 -07001508
Maggie Zhangf7f738122010-12-09 19:08:43 -08001509 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1510 pgoff = PSS_SMEM_PGOFF(loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001511
Jing Huang53440262010-10-18 17:12:29 -07001512 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001513
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001514 for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001515
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001516 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1517 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001518 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001519 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
Jing Huang7725ccf2009-09-23 17:46:15 -07001520 }
1521
Jing Huang5fbe25c2010-10-18 17:17:23 -07001522 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001523 * write smem
1524 */
1525 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001526 fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
Jing Huang7725ccf2009-09-23 17:46:15 -07001527
1528 loff += sizeof(u32);
1529
Jing Huang5fbe25c2010-10-18 17:17:23 -07001530 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001531 * handle page offset wrap around
1532 */
1533 loff = PSS_SMEM_PGOFF(loff);
1534 if (loff == 0) {
1535 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001536 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001537 }
1538 }
1539
Maggie Zhangf7f738122010-12-09 19:08:43 -08001540 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1541 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001542
1543 /*
1544 * Set boot type and boot param at the end.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001545 */
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001546 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001547 swab32(boot_type));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001548 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001549 swab32(boot_env));
Jing Huang7725ccf2009-09-23 17:46:15 -07001550}
1551
Jing Huang7725ccf2009-09-23 17:46:15 -07001552
Jing Huang5fbe25c2010-10-18 17:17:23 -07001553/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001554 * Update BFA configuration from firmware configuration.
1555 */
1556static void
1557bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1558{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001559 struct bfi_ioc_attr_s *attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001560
Jing Huangba816ea2010-10-18 17:10:50 -07001561 attr->adapter_prop = be32_to_cpu(attr->adapter_prop);
1562 attr->card_type = be32_to_cpu(attr->card_type);
1563 attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
Jing Huang7725ccf2009-09-23 17:46:15 -07001564
1565 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1566}
1567
Jing Huang5fbe25c2010-10-18 17:17:23 -07001568/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001569 * Attach time initialization of mbox logic.
1570 */
1571static void
1572bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1573{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001574 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1575 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001576
1577 INIT_LIST_HEAD(&mod->cmd_q);
1578 for (mc = 0; mc < BFI_MC_MAX; mc++) {
1579 mod->mbhdlr[mc].cbfn = NULL;
1580 mod->mbhdlr[mc].cbarg = ioc->bfa;
1581 }
1582}
1583
Jing Huang5fbe25c2010-10-18 17:17:23 -07001584/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001585 * Mbox poll timer -- restarts any pending mailbox requests.
1586 */
1587static void
1588bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1589{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001590 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1591 struct bfa_mbox_cmd_s *cmd;
1592 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07001593
Jing Huang5fbe25c2010-10-18 17:17:23 -07001594 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001595 * If no command pending, do nothing
1596 */
1597 if (list_empty(&mod->cmd_q))
1598 return;
1599
Jing Huang5fbe25c2010-10-18 17:17:23 -07001600 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001601 * If previous command is not yet fetched by firmware, do nothing
1602 */
Jing Huang53440262010-10-18 17:12:29 -07001603 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001604 if (stat)
1605 return;
1606
Jing Huang5fbe25c2010-10-18 17:17:23 -07001607 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001608 * Enqueue command to firmware.
1609 */
1610 bfa_q_deq(&mod->cmd_q, &cmd);
1611 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1612}
1613
Jing Huang5fbe25c2010-10-18 17:17:23 -07001614/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001615 * Cleanup any pending requests.
1616 */
1617static void
1618bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
1619{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001620 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1621 struct bfa_mbox_cmd_s *cmd;
Jing Huang7725ccf2009-09-23 17:46:15 -07001622
1623 while (!list_empty(&mod->cmd_q))
1624 bfa_q_deq(&mod->cmd_q, &cmd);
1625}
1626
Jing Huang5fbe25c2010-10-18 17:17:23 -07001627/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001628 * Read data from SMEM to host through PCI memmap
1629 *
1630 * @param[in] ioc memory for IOC
1631 * @param[in] tbuf app memory to store data from smem
1632 * @param[in] soff smem offset
1633 * @param[in] sz size of smem in bytes
Jing Huang7725ccf2009-09-23 17:46:15 -07001634 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001635static bfa_status_t
1636bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
1637{
Maggie50444a32010-11-29 18:26:32 -08001638 u32 pgnum, loff;
1639 __be32 r32;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001640 int i, len;
1641 u32 *buf = tbuf;
1642
Maggie Zhangf7f738122010-12-09 19:08:43 -08001643 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1644 loff = PSS_SMEM_PGOFF(soff);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001645 bfa_trc(ioc, pgnum);
1646 bfa_trc(ioc, loff);
1647 bfa_trc(ioc, sz);
1648
1649 /*
1650 * Hold semaphore to serialize pll init and fwtrc.
1651 */
1652 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1653 bfa_trc(ioc, 0);
1654 return BFA_STATUS_FAILED;
1655 }
1656
Jing Huang53440262010-10-18 17:12:29 -07001657 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001658
1659 len = sz/sizeof(u32);
1660 bfa_trc(ioc, len);
1661 for (i = 0; i < len; i++) {
1662 r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huangba816ea2010-10-18 17:10:50 -07001663 buf[i] = be32_to_cpu(r32);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001664 loff += sizeof(u32);
1665
Jing Huang5fbe25c2010-10-18 17:17:23 -07001666 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001667 * handle page offset wrap around
1668 */
1669 loff = PSS_SMEM_PGOFF(loff);
1670 if (loff == 0) {
1671 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001672 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001673 }
1674 }
Maggie Zhangf7f738122010-12-09 19:08:43 -08001675 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1676 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001677 /*
1678 * release semaphore.
1679 */
Maggie Zhangf7f738122010-12-09 19:08:43 -08001680 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001681
1682 bfa_trc(ioc, pgnum);
1683 return BFA_STATUS_OK;
1684}
1685
Jing Huang5fbe25c2010-10-18 17:17:23 -07001686/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001687 * Clear SMEM data from host through PCI memmap
1688 *
1689 * @param[in] ioc memory for IOC
1690 * @param[in] soff smem offset
1691 * @param[in] sz size of smem in bytes
1692 */
1693static bfa_status_t
1694bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
1695{
1696 int i, len;
1697 u32 pgnum, loff;
1698
Maggie Zhangf7f738122010-12-09 19:08:43 -08001699 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1700 loff = PSS_SMEM_PGOFF(soff);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001701 bfa_trc(ioc, pgnum);
1702 bfa_trc(ioc, loff);
1703 bfa_trc(ioc, sz);
1704
1705 /*
1706 * Hold semaphore to serialize pll init and fwtrc.
1707 */
1708 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1709 bfa_trc(ioc, 0);
1710 return BFA_STATUS_FAILED;
1711 }
1712
Jing Huang53440262010-10-18 17:12:29 -07001713 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001714
1715 len = sz/sizeof(u32); /* len in words */
1716 bfa_trc(ioc, len);
1717 for (i = 0; i < len; i++) {
1718 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
1719 loff += sizeof(u32);
1720
Jing Huang5fbe25c2010-10-18 17:17:23 -07001721 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001722 * handle page offset wrap around
1723 */
1724 loff = PSS_SMEM_PGOFF(loff);
1725 if (loff == 0) {
1726 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001727 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001728 }
1729 }
Maggie Zhangf7f738122010-12-09 19:08:43 -08001730 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1731 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001732
1733 /*
1734 * release semaphore.
1735 */
Maggie Zhangf7f738122010-12-09 19:08:43 -08001736 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001737 bfa_trc(ioc, pgnum);
1738 return BFA_STATUS_OK;
1739}
1740
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001741
1742static void
1743bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
1744{
1745 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Jing Huang5fbe25c2010-10-18 17:17:23 -07001746 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001747 * Provide enable completion callback.
1748 */
1749 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Jing Huang88166242010-12-09 17:11:53 -08001750 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001751 "Running firmware version is incompatible "
1752 "with the driver version\n");
1753}
1754
1755
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001756bfa_status_t
1757bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1758{
1759
1760 /*
1761 * Hold semaphore so that nobody can access the chip during init.
1762 */
1763 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1764
1765 bfa_ioc_pll_init_asic(ioc);
1766
1767 ioc->pllinit = BFA_TRUE;
1768 /*
1769 * release semaphore.
1770 */
Maggie Zhangf7f738122010-12-09 19:08:43 -08001771 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001772
1773 return BFA_STATUS_OK;
1774}
Jing Huang7725ccf2009-09-23 17:46:15 -07001775
Jing Huang5fbe25c2010-10-18 17:17:23 -07001776/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001777 * Interface used by diag module to do firmware boot with memory test
1778 * as the entry vector.
1779 */
1780void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001781bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001782{
Jing Huang53440262010-10-18 17:12:29 -07001783 void __iomem *rb;
Jing Huang7725ccf2009-09-23 17:46:15 -07001784
1785 bfa_ioc_stats(ioc, ioc_boots);
1786
1787 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1788 return;
1789
Jing Huang5fbe25c2010-10-18 17:17:23 -07001790 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001791 * Initialize IOC state of all functions on a chip reset.
1792 */
1793 rb = ioc->pcidev.pci_bar_kva;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001794 if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
Jing Huang53440262010-10-18 17:12:29 -07001795 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
1796 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
Jing Huang7725ccf2009-09-23 17:46:15 -07001797 } else {
Jing Huang53440262010-10-18 17:12:29 -07001798 writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
1799 writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
Jing Huang7725ccf2009-09-23 17:46:15 -07001800 }
1801
Jing Huang07b28382010-07-08 19:59:24 -07001802 bfa_ioc_msgflush(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001803 bfa_ioc_download_fw(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001804
Jing Huang5fbe25c2010-10-18 17:17:23 -07001805 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001806 * Enable interrupts just before starting LPU
1807 */
1808 ioc->cbfn->reset_cbfn(ioc->bfa);
1809 bfa_ioc_lpu_start(ioc);
1810}
1811
Jing Huang5fbe25c2010-10-18 17:17:23 -07001812/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001813 * Enable/disable IOC failure auto recovery.
1814 */
1815void
1816bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
1817{
Krishna Gudipati2f9b8852010-03-03 17:42:51 -08001818 bfa_auto_recover = auto_recover;
Jing Huang7725ccf2009-09-23 17:46:15 -07001819}
1820
1821
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001822
Jing Huang7725ccf2009-09-23 17:46:15 -07001823bfa_boolean_t
1824bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
1825{
1826 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
1827}
1828
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001829bfa_boolean_t
1830bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
1831{
Jing Huang53440262010-10-18 17:12:29 -07001832 u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001833
1834 return ((r32 != BFI_IOC_UNINIT) &&
1835 (r32 != BFI_IOC_INITING) &&
1836 (r32 != BFI_IOC_MEMTEST));
1837}
1838
Jing Huang7725ccf2009-09-23 17:46:15 -07001839void
1840bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
1841{
Maggie50444a32010-11-29 18:26:32 -08001842 __be32 *msgp = mbmsg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001843 u32 r32;
1844 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001845
Jing Huang5fbe25c2010-10-18 17:17:23 -07001846 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001847 * read the MBOX msg
1848 */
1849 for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
1850 i++) {
Jing Huang53440262010-10-18 17:12:29 -07001851 r32 = readl(ioc->ioc_regs.lpu_mbox +
Jing Huang7725ccf2009-09-23 17:46:15 -07001852 i * sizeof(u32));
Jing Huangba816ea2010-10-18 17:10:50 -07001853 msgp[i] = cpu_to_be32(r32);
Jing Huang7725ccf2009-09-23 17:46:15 -07001854 }
1855
Jing Huang5fbe25c2010-10-18 17:17:23 -07001856 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001857 * turn off mailbox interrupt by clearing mailbox status
1858 */
Jing Huang53440262010-10-18 17:12:29 -07001859 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1860 readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001861}
1862
1863void
1864bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
1865{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001866 union bfi_ioc_i2h_msg_u *msg;
1867 struct bfa_iocpf_s *iocpf = &ioc->iocpf;
Jing Huang7725ccf2009-09-23 17:46:15 -07001868
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001869 msg = (union bfi_ioc_i2h_msg_u *) m;
Jing Huang7725ccf2009-09-23 17:46:15 -07001870
1871 bfa_ioc_stats(ioc, ioc_isrs);
1872
1873 switch (msg->mh.msg_id) {
1874 case BFI_IOC_I2H_HBEAT:
1875 break;
1876
1877 case BFI_IOC_I2H_READY_EVENT:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001878 bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001879 break;
1880
1881 case BFI_IOC_I2H_ENABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001882 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001883 break;
1884
1885 case BFI_IOC_I2H_DISABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001886 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001887 break;
1888
1889 case BFI_IOC_I2H_GETATTR_REPLY:
1890 bfa_ioc_getattr_reply(ioc);
1891 break;
1892
1893 default:
1894 bfa_trc(ioc, msg->mh.msg_id);
1895 bfa_assert(0);
1896 }
1897}
1898
Jing Huang5fbe25c2010-10-18 17:17:23 -07001899/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001900 * IOC attach time initialization and setup.
1901 *
1902 * @param[in] ioc memory for IOC
1903 * @param[in] bfa driver instance structure
Jing Huang7725ccf2009-09-23 17:46:15 -07001904 */
1905void
1906bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001907 struct bfa_timer_mod_s *timer_mod)
Jing Huang7725ccf2009-09-23 17:46:15 -07001908{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001909 ioc->bfa = bfa;
1910 ioc->cbfn = cbfn;
1911 ioc->timer_mod = timer_mod;
1912 ioc->fcmode = BFA_FALSE;
1913 ioc->pllinit = BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001914 ioc->dbg_fwsave_once = BFA_TRUE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001915 ioc->iocpf.ioc = ioc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001916
1917 bfa_ioc_mbox_attach(ioc);
1918 INIT_LIST_HEAD(&ioc->hb_notify_q);
1919
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001920 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
1921 bfa_fsm_send_event(ioc, IOC_E_RESET);
Jing Huang7725ccf2009-09-23 17:46:15 -07001922}
1923
Jing Huang5fbe25c2010-10-18 17:17:23 -07001924/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001925 * Driver detach time IOC cleanup.
1926 */
1927void
1928bfa_ioc_detach(struct bfa_ioc_s *ioc)
1929{
1930 bfa_fsm_send_event(ioc, IOC_E_DETACH);
1931}
1932
Jing Huang5fbe25c2010-10-18 17:17:23 -07001933/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001934 * Setup IOC PCI properties.
1935 *
1936 * @param[in] pcidev PCI device information for this IOC
1937 */
1938void
1939bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
1940 enum bfi_mclass mc)
1941{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001942 ioc->ioc_mc = mc;
1943 ioc->pcidev = *pcidev;
1944 ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
1945 ioc->cna = ioc->ctdev && !ioc->fcmode;
Jing Huang7725ccf2009-09-23 17:46:15 -07001946
Jing Huang5fbe25c2010-10-18 17:17:23 -07001947 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001948 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
1949 */
1950 if (ioc->ctdev)
1951 bfa_ioc_set_ct_hwif(ioc);
1952 else
1953 bfa_ioc_set_cb_hwif(ioc);
1954
Jing Huang7725ccf2009-09-23 17:46:15 -07001955 bfa_ioc_map_port(ioc);
1956 bfa_ioc_reg_init(ioc);
1957}
1958
Jing Huang5fbe25c2010-10-18 17:17:23 -07001959/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001960 * Initialize IOC dma memory
1961 *
1962 * @param[in] dm_kva kernel virtual address of IOC dma memory
1963 * @param[in] dm_pa physical address of IOC dma memory
1964 */
1965void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001966bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
Jing Huang7725ccf2009-09-23 17:46:15 -07001967{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001968 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001969 * dma memory for firmware attribute
1970 */
1971 ioc->attr_dma.kva = dm_kva;
1972 ioc->attr_dma.pa = dm_pa;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001973 ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07001974}
1975
Jing Huang7725ccf2009-09-23 17:46:15 -07001976void
1977bfa_ioc_enable(struct bfa_ioc_s *ioc)
1978{
1979 bfa_ioc_stats(ioc, ioc_enables);
1980 ioc->dbg_fwsave_once = BFA_TRUE;
1981
1982 bfa_fsm_send_event(ioc, IOC_E_ENABLE);
1983}
1984
1985void
1986bfa_ioc_disable(struct bfa_ioc_s *ioc)
1987{
1988 bfa_ioc_stats(ioc, ioc_disables);
1989 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
1990}
1991
Jing Huang7725ccf2009-09-23 17:46:15 -07001992
Jing Huang5fbe25c2010-10-18 17:17:23 -07001993/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001994 * Initialize memory for saving firmware trace. Driver must initialize
1995 * trace memory before call bfa_ioc_enable().
1996 */
1997void
1998bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
1999{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002000 ioc->dbg_fwsave = dbg_fwsave;
Maggie Zhangf7f738122010-12-09 19:08:43 -08002001 ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
Jing Huang7725ccf2009-09-23 17:46:15 -07002002}
2003
Jing Huang5fbe25c2010-10-18 17:17:23 -07002004/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002005 * Register mailbox message handler functions
2006 *
2007 * @param[in] ioc IOC instance
2008 * @param[in] mcfuncs message class handler functions
2009 */
2010void
2011bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
2012{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002013 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2014 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002015
2016 for (mc = 0; mc < BFI_MC_MAX; mc++)
2017 mod->mbhdlr[mc].cbfn = mcfuncs[mc];
2018}
2019
Jing Huang5fbe25c2010-10-18 17:17:23 -07002020/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002021 * Register mailbox message handler function, to be called by common modules
2022 */
2023void
2024bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
2025 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2026{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002027 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
Jing Huang7725ccf2009-09-23 17:46:15 -07002028
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002029 mod->mbhdlr[mc].cbfn = cbfn;
2030 mod->mbhdlr[mc].cbarg = cbarg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002031}
2032
Jing Huang5fbe25c2010-10-18 17:17:23 -07002033/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002034 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2035 * Responsibility of caller to serialize
2036 *
2037 * @param[in] ioc IOC instance
2038 * @param[i] cmd Mailbox command
2039 */
2040void
2041bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
2042{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002043 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2044 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07002045
Jing Huang5fbe25c2010-10-18 17:17:23 -07002046 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002047 * If a previous command is pending, queue new command
2048 */
2049 if (!list_empty(&mod->cmd_q)) {
2050 list_add_tail(&cmd->qe, &mod->cmd_q);
2051 return;
2052 }
2053
Jing Huang5fbe25c2010-10-18 17:17:23 -07002054 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002055 * If mailbox is busy, queue command for poll timer
2056 */
Jing Huang53440262010-10-18 17:12:29 -07002057 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07002058 if (stat) {
2059 list_add_tail(&cmd->qe, &mod->cmd_q);
2060 return;
2061 }
2062
Jing Huang5fbe25c2010-10-18 17:17:23 -07002063 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002064 * mailbox is free -- queue command to firmware
2065 */
2066 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
2067}
2068
Jing Huang5fbe25c2010-10-18 17:17:23 -07002069/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002070 * Handle mailbox interrupts
2071 */
2072void
2073bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
2074{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002075 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2076 struct bfi_mbmsg_s m;
2077 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002078
2079 bfa_ioc_msgget(ioc, &m);
2080
Jing Huang5fbe25c2010-10-18 17:17:23 -07002081 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002082 * Treat IOC message class as special.
2083 */
2084 mc = m.mh.msg_class;
2085 if (mc == BFI_MC_IOC) {
2086 bfa_ioc_isr(ioc, &m);
2087 return;
2088 }
2089
2090 if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2091 return;
2092
2093 mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
2094}
2095
2096void
2097bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
2098{
2099 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2100}
2101
Jing Huanged969322010-07-08 19:45:56 -07002102void
2103bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
2104{
2105 ioc->fcmode = BFA_TRUE;
2106 ioc->port_id = bfa_ioc_pcifn(ioc);
2107}
2108
Jing Huang5fbe25c2010-10-18 17:17:23 -07002109/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002110 * return true if IOC is disabled
2111 */
2112bfa_boolean_t
2113bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
2114{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002115 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2116 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
Jing Huang7725ccf2009-09-23 17:46:15 -07002117}
2118
Jing Huang5fbe25c2010-10-18 17:17:23 -07002119/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002120 * return true if IOC firmware is different.
2121 */
2122bfa_boolean_t
2123bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2124{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002125 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
2126 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
2127 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
Jing Huang7725ccf2009-09-23 17:46:15 -07002128}
2129
2130#define bfa_ioc_state_disabled(__sm) \
2131 (((__sm) == BFI_IOC_UNINIT) || \
2132 ((__sm) == BFI_IOC_INITING) || \
2133 ((__sm) == BFI_IOC_HWINIT) || \
2134 ((__sm) == BFI_IOC_DISABLED) || \
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002135 ((__sm) == BFI_IOC_FAIL) || \
Jing Huang7725ccf2009-09-23 17:46:15 -07002136 ((__sm) == BFI_IOC_CFG_DISABLED))
2137
Jing Huang5fbe25c2010-10-18 17:17:23 -07002138/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002139 * Check if adapter is disabled -- both IOCs should be in a disabled
2140 * state.
2141 */
2142bfa_boolean_t
2143bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
2144{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002145 u32 ioc_state;
Jing Huang53440262010-10-18 17:12:29 -07002146 void __iomem *rb = ioc->pcidev.pci_bar_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07002147
2148 if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
2149 return BFA_FALSE;
2150
Jing Huang53440262010-10-18 17:12:29 -07002151 ioc_state = readl(rb + BFA_IOC0_STATE_REG);
Jing Huang7725ccf2009-09-23 17:46:15 -07002152 if (!bfa_ioc_state_disabled(ioc_state))
2153 return BFA_FALSE;
2154
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002155 if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
Jing Huang53440262010-10-18 17:12:29 -07002156 ioc_state = readl(rb + BFA_IOC1_STATE_REG);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002157 if (!bfa_ioc_state_disabled(ioc_state))
2158 return BFA_FALSE;
2159 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002160
2161 return BFA_TRUE;
2162}
2163
Jing Huang7725ccf2009-09-23 17:46:15 -07002164#define BFA_MFG_NAME "Brocade"
2165void
2166bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2167 struct bfa_adapter_attr_s *ad_attr)
2168{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002169 struct bfi_ioc_attr_s *ioc_attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002170
2171 ioc_attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002172
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002173 bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2174 bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2175 bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2176 bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
Jing Huang6a18b162010-10-18 17:08:54 -07002177 memcpy(&ad_attr->vpd, &ioc_attr->vpd,
Jing Huang7725ccf2009-09-23 17:46:15 -07002178 sizeof(struct bfa_mfg_vpd_s));
2179
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002180 ad_attr->nports = bfa_ioc_get_nports(ioc);
2181 ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002182
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002183 bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2184 /* For now, model descr uses same model string */
2185 bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
Jing Huang7725ccf2009-09-23 17:46:15 -07002186
Jing Huanged969322010-07-08 19:45:56 -07002187 ad_attr->card_type = ioc_attr->card_type;
2188 ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2189
Jing Huang7725ccf2009-09-23 17:46:15 -07002190 if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2191 ad_attr->prototype = 1;
2192 else
2193 ad_attr->prototype = 0;
2194
Maggie Zhangf7f738122010-12-09 19:08:43 -08002195 ad_attr->pwwn = ioc->attr->pwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002196 ad_attr->mac = bfa_ioc_get_mac(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002197
2198 ad_attr->pcie_gen = ioc_attr->pcie_gen;
2199 ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2200 ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2201 ad_attr->asic_rev = ioc_attr->asic_rev;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002202
2203 bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
Jing Huang7725ccf2009-09-23 17:46:15 -07002204
2205 ad_attr->cna_capable = ioc->cna;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002206 ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
Jing Huang7725ccf2009-09-23 17:46:15 -07002207}
2208
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002209enum bfa_ioc_type_e
2210bfa_ioc_get_type(struct bfa_ioc_s *ioc)
2211{
2212 if (!ioc->ctdev || ioc->fcmode)
2213 return BFA_IOC_TYPE_FC;
2214 else if (ioc->ioc_mc == BFI_MC_IOCFC)
2215 return BFA_IOC_TYPE_FCoE;
2216 else if (ioc->ioc_mc == BFI_MC_LL)
2217 return BFA_IOC_TYPE_LL;
2218 else {
2219 bfa_assert(ioc->ioc_mc == BFI_MC_LL);
2220 return BFA_IOC_TYPE_LL;
2221 }
2222}
2223
Jing Huang7725ccf2009-09-23 17:46:15 -07002224void
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002225bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)
2226{
Jing Huang6a18b162010-10-18 17:08:54 -07002227 memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2228 memcpy((void *)serial_num,
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002229 (void *)ioc->attr->brcd_serialnum,
2230 BFA_ADAPTER_SERIAL_NUM_LEN);
2231}
2232
2233void
2234bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
2235{
Jing Huang6a18b162010-10-18 17:08:54 -07002236 memset((void *)fw_ver, 0, BFA_VERSION_LEN);
2237 memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002238}
2239
2240void
2241bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
2242{
2243 bfa_assert(chip_rev);
2244
Jing Huang6a18b162010-10-18 17:08:54 -07002245 memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002246
2247 chip_rev[0] = 'R';
2248 chip_rev[1] = 'e';
2249 chip_rev[2] = 'v';
2250 chip_rev[3] = '-';
2251 chip_rev[4] = ioc->attr->asic_rev;
2252 chip_rev[5] = '\0';
2253}
2254
2255void
2256bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
2257{
Jing Huang6a18b162010-10-18 17:08:54 -07002258 memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
2259 memcpy(optrom_ver, ioc->attr->optrom_version,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002260 BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002261}
2262
2263void
2264bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
2265{
Jing Huang6a18b162010-10-18 17:08:54 -07002266 memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2267 memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002268}
2269
2270void
2271bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
2272{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002273 struct bfi_ioc_attr_s *ioc_attr;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002274
2275 bfa_assert(model);
Jing Huang6a18b162010-10-18 17:08:54 -07002276 memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002277
2278 ioc_attr = ioc->attr;
2279
Jing Huang5fbe25c2010-10-18 17:17:23 -07002280 /*
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002281 * model name
2282 */
Jing Huang6a18b162010-10-18 17:08:54 -07002283 snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002284 BFA_MFG_NAME, ioc_attr->card_type);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002285}
2286
2287enum bfa_ioc_state
2288bfa_ioc_get_state(struct bfa_ioc_s *ioc)
2289{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002290 enum bfa_iocpf_state iocpf_st;
2291 enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2292
2293 if (ioc_st == BFA_IOC_ENABLING ||
2294 ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2295
2296 iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2297
2298 switch (iocpf_st) {
2299 case BFA_IOCPF_SEMWAIT:
2300 ioc_st = BFA_IOC_SEMWAIT;
2301 break;
2302
2303 case BFA_IOCPF_HWINIT:
2304 ioc_st = BFA_IOC_HWINIT;
2305 break;
2306
2307 case BFA_IOCPF_FWMISMATCH:
2308 ioc_st = BFA_IOC_FWMISMATCH;
2309 break;
2310
2311 case BFA_IOCPF_FAIL:
2312 ioc_st = BFA_IOC_FAIL;
2313 break;
2314
2315 case BFA_IOCPF_INITFAIL:
2316 ioc_st = BFA_IOC_INITFAIL;
2317 break;
2318
2319 default:
2320 break;
2321 }
2322 }
2323
2324 return ioc_st;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002325}
2326
2327void
Jing Huang7725ccf2009-09-23 17:46:15 -07002328bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2329{
Jing Huang6a18b162010-10-18 17:08:54 -07002330 memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
Jing Huang7725ccf2009-09-23 17:46:15 -07002331
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002332 ioc_attr->state = bfa_ioc_get_state(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002333 ioc_attr->port_id = ioc->port_id;
2334
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002335 ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002336
2337 bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2338
2339 ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2340 ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002341 bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
Jing Huang7725ccf2009-09-23 17:46:15 -07002342}
2343
Jing Huang7725ccf2009-09-23 17:46:15 -07002344mac_t
2345bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2346{
Jing Huang15b64a82010-07-08 19:48:12 -07002347 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002348 * Check the IOC type and return the appropriate MAC
Jing Huang15b64a82010-07-08 19:48:12 -07002349 */
2350 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002351 return ioc->attr->fcoe_mac;
Jing Huang15b64a82010-07-08 19:48:12 -07002352 else
2353 return ioc->attr->mac;
2354}
2355
Jing Huang15b64a82010-07-08 19:48:12 -07002356mac_t
2357bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
2358{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002359 mac_t m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002360
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002361 m = ioc->attr->mfg_mac;
2362 if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
2363 m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2364 else
2365 bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
2366 bfa_ioc_pcifn(ioc));
Jing Huang7725ccf2009-09-23 17:46:15 -07002367
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002368 return m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002369}
2370
Jing Huang7725ccf2009-09-23 17:46:15 -07002371bfa_boolean_t
2372bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
2373{
Jing Huang293f82d2010-07-08 19:45:20 -07002374 return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id);
Jing Huang7725ccf2009-09-23 17:46:15 -07002375}
2376
Jing Huang5fbe25c2010-10-18 17:17:23 -07002377/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002378 * Retrieve saved firmware trace from a prior IOC failure.
2379 */
2380bfa_status_t
2381bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2382{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002383 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002384
2385 if (ioc->dbg_fwsave_len == 0)
2386 return BFA_STATUS_ENOFSAVE;
2387
2388 tlen = *trclen;
2389 if (tlen > ioc->dbg_fwsave_len)
2390 tlen = ioc->dbg_fwsave_len;
2391
Jing Huang6a18b162010-10-18 17:08:54 -07002392 memcpy(trcdata, ioc->dbg_fwsave, tlen);
Jing Huang7725ccf2009-09-23 17:46:15 -07002393 *trclen = tlen;
2394 return BFA_STATUS_OK;
2395}
2396
Krishna Gudipati738c9e62010-03-05 19:36:19 -08002397
Jing Huang5fbe25c2010-10-18 17:17:23 -07002398/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002399 * Retrieve saved firmware trace from a prior IOC failure.
2400 */
2401bfa_status_t
2402bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2403{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002404 u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2405 int tlen;
2406 bfa_status_t status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002407
2408 bfa_trc(ioc, *trclen);
2409
Jing Huang7725ccf2009-09-23 17:46:15 -07002410 tlen = *trclen;
2411 if (tlen > BFA_DBG_FWTRC_LEN)
2412 tlen = BFA_DBG_FWTRC_LEN;
Jing Huang7725ccf2009-09-23 17:46:15 -07002413
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002414 status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
2415 *trclen = tlen;
2416 return status;
2417}
Jing Huang7725ccf2009-09-23 17:46:15 -07002418
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002419static void
2420bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
2421{
2422 struct bfa_mbox_cmd_s cmd;
2423 struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002424
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002425 bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
2426 bfa_ioc_portid(ioc));
2427 req->ioc_class = ioc->ioc_mc;
2428 bfa_ioc_mbox_queue(ioc, &cmd);
2429}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002430
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002431static void
2432bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
2433{
2434 u32 fwsync_iter = 1000;
2435
2436 bfa_ioc_send_fwsync(ioc);
2437
Jing Huang5fbe25c2010-10-18 17:17:23 -07002438 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002439 * After sending a fw sync mbox command wait for it to
2440 * take effect. We will not wait for a response because
2441 * 1. fw_sync mbox cmd doesn't have a response.
2442 * 2. Even if we implement that, interrupts might not
2443 * be enabled when we call this function.
2444 * So, just keep checking if any mbox cmd is pending, and
2445 * after waiting for a reasonable amount of time, go ahead.
2446 * It is possible that fw has crashed and the mbox command
2447 * is never acknowledged.
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002448 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002449 while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
2450 fwsync_iter--;
2451}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002452
Jing Huang5fbe25c2010-10-18 17:17:23 -07002453/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002454 * Dump firmware smem
2455 */
2456bfa_status_t
2457bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
2458 u32 *offset, int *buflen)
2459{
2460 u32 loff;
2461 int dlen;
2462 bfa_status_t status;
2463 u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002464
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002465 if (*offset >= smem_len) {
2466 *offset = *buflen = 0;
2467 return BFA_STATUS_EINVAL;
2468 }
2469
2470 loff = *offset;
2471 dlen = *buflen;
2472
Jing Huang5fbe25c2010-10-18 17:17:23 -07002473 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002474 * First smem read, sync smem before proceeding
2475 * No need to sync before reading every chunk.
2476 */
2477 if (loff == 0)
2478 bfa_ioc_fwsync(ioc);
2479
2480 if ((loff + dlen) >= smem_len)
2481 dlen = smem_len - loff;
2482
2483 status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
2484
2485 if (status != BFA_STATUS_OK) {
2486 *offset = *buflen = 0;
2487 return status;
2488 }
2489
2490 *offset += dlen;
2491
2492 if (*offset >= smem_len)
2493 *offset = 0;
2494
2495 *buflen = dlen;
2496
2497 return status;
2498}
2499
Jing Huang5fbe25c2010-10-18 17:17:23 -07002500/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002501 * Firmware statistics
2502 */
2503bfa_status_t
2504bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
2505{
2506 u32 loff = BFI_IOC_FWSTATS_OFF + \
2507 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2508 int tlen;
2509 bfa_status_t status;
2510
2511 if (ioc->stats_busy) {
2512 bfa_trc(ioc, ioc->stats_busy);
2513 return BFA_STATUS_DEVBUSY;
2514 }
2515 ioc->stats_busy = BFA_TRUE;
2516
2517 tlen = sizeof(struct bfa_fw_stats_s);
2518 status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
2519
2520 ioc->stats_busy = BFA_FALSE;
2521 return status;
2522}
2523
2524bfa_status_t
2525bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2526{
2527 u32 loff = BFI_IOC_FWSTATS_OFF + \
2528 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2529 int tlen;
2530 bfa_status_t status;
2531
2532 if (ioc->stats_busy) {
2533 bfa_trc(ioc, ioc->stats_busy);
2534 return BFA_STATUS_DEVBUSY;
2535 }
2536 ioc->stats_busy = BFA_TRUE;
2537
2538 tlen = sizeof(struct bfa_fw_stats_s);
2539 status = bfa_ioc_smem_clr(ioc, loff, tlen);
2540
2541 ioc->stats_busy = BFA_FALSE;
2542 return status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002543}
2544
Jing Huang5fbe25c2010-10-18 17:17:23 -07002545/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002546 * Save firmware trace if configured.
2547 */
2548static void
2549bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
2550{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002551 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002552
2553 if (ioc->dbg_fwsave_len) {
2554 tlen = ioc->dbg_fwsave_len;
2555 bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2556 }
2557}
2558
Jing Huang5fbe25c2010-10-18 17:17:23 -07002559/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002560 * Firmware failure detected. Start recovery actions.
2561 */
2562static void
2563bfa_ioc_recover(struct bfa_ioc_s *ioc)
2564{
2565 if (ioc->dbg_fwsave_once) {
2566 ioc->dbg_fwsave_once = BFA_FALSE;
2567 bfa_ioc_debug_save(ioc);
2568 }
2569
2570 bfa_ioc_stats(ioc, ioc_hbfails);
2571 bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2572}
2573
Jing Huang7725ccf2009-09-23 17:46:15 -07002574static void
Jing Huang07b28382010-07-08 19:59:24 -07002575bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -07002576{
Jing Huang07b28382010-07-08 19:59:24 -07002577 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
2578 return;
Jing Huang7725ccf2009-09-23 17:46:15 -07002579}
2580
Jing Huang5fbe25c2010-10-18 17:17:23 -07002581/*
Maggie Zhangdf0f1932010-12-09 19:07:46 -08002582 * BFA IOC PF private functions
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002583 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002584static void
2585bfa_iocpf_timeout(void *ioc_arg)
2586{
2587 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2588
2589 bfa_trc(ioc, 0);
2590 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
2591}
2592
2593static void
2594bfa_iocpf_sem_timeout(void *ioc_arg)
2595{
2596 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2597
2598 bfa_ioc_hw_sem_get(ioc);
2599}
2600
Jing Huang5fbe25c2010-10-18 17:17:23 -07002601/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002602 * bfa timer function
2603 */
2604void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002605bfa_timer_beat(struct bfa_timer_mod_s *mod)
2606{
2607 struct list_head *qh = &mod->timer_q;
2608 struct list_head *qe, *qe_next;
2609 struct bfa_timer_s *elem;
2610 struct list_head timedout_q;
2611
2612 INIT_LIST_HEAD(&timedout_q);
2613
2614 qe = bfa_q_next(qh);
2615
2616 while (qe != qh) {
2617 qe_next = bfa_q_next(qe);
2618
2619 elem = (struct bfa_timer_s *) qe;
2620 if (elem->timeout <= BFA_TIMER_FREQ) {
2621 elem->timeout = 0;
2622 list_del(&elem->qe);
2623 list_add_tail(&elem->qe, &timedout_q);
2624 } else {
2625 elem->timeout -= BFA_TIMER_FREQ;
2626 }
2627
2628 qe = qe_next; /* go to next elem */
2629 }
2630
2631 /*
2632 * Pop all the timeout entries
2633 */
2634 while (!list_empty(&timedout_q)) {
2635 bfa_q_deq(&timedout_q, &elem);
2636 elem->timercb(elem->arg);
2637 }
2638}
2639
Jing Huang5fbe25c2010-10-18 17:17:23 -07002640/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002641 * Should be called with lock protection
2642 */
2643void
2644bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
2645 void (*timercb) (void *), void *arg, unsigned int timeout)
2646{
2647
2648 bfa_assert(timercb != NULL);
2649 bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
2650
2651 timer->timeout = timeout;
2652 timer->timercb = timercb;
2653 timer->arg = arg;
2654
2655 list_add_tail(&timer->qe, &mod->timer_q);
2656}
2657
Jing Huang5fbe25c2010-10-18 17:17:23 -07002658/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002659 * Should be called with lock protection
2660 */
2661void
2662bfa_timer_stop(struct bfa_timer_s *timer)
2663{
2664 bfa_assert(!list_empty(&timer->qe));
2665
2666 list_del(&timer->qe);
2667}