blob: 9e82eea9b2b098f225987c2663c7a3f0f5345a64 [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_ENTS (BFI_IOC_TRC_ENTS)
46#define BFA_DBG_FWTRC_LEN \
47 (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \
48 (sizeof(struct bfa_trc_mod_s) - \
49 BFA_TRC_MAX * sizeof(struct bfa_trc_s)))
50#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
Jing Huang7725ccf2009-09-23 17:46:15 -070051
Jing Huang5fbe25c2010-10-18 17:17:23 -070052/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080053 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
54 */
55
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070056#define bfa_ioc_firmware_lock(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080057 ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070058#define bfa_ioc_firmware_unlock(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080059 ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
Krishna Gudipati0a20de42010-03-05 19:34:20 -080060#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
61#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070062#define bfa_ioc_notify_hbfail(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080063 ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
64
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070065#ifdef BFA_IOC_IS_UEFI
66#define bfa_ioc_is_bios_optrom(__ioc) (0)
67#define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI
68#else
69#define bfa_ioc_is_bios_optrom(__ioc) \
70 (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
71#define bfa_ioc_is_uefi(__ioc) (0)
72#endif
73
74#define bfa_ioc_mbox_cmd_pending(__ioc) \
75 (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
Jing Huang53440262010-10-18 17:12:29 -070076 readl((__ioc)->ioc_regs.hfn_mbox_cmd))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070077
78bfa_boolean_t bfa_auto_recover = BFA_TRUE;
Jing Huang7725ccf2009-09-23 17:46:15 -070079
80/*
81 * forward declarations
82 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070083static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
84static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc);
85static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
86static void bfa_ioc_timeout(void *ioc);
87static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
88static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
89static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
90static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
91static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc);
92static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force);
93static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
94static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
95static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
96static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
97static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
98static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
99static void bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc);
100static void bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc);
101static void bfa_ioc_pf_failed(struct bfa_ioc_s *ioc);
102static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700103
Jing Huang5fbe25c2010-10-18 17:17:23 -0700104/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700105 * hal_ioc_sm
Jing Huang7725ccf2009-09-23 17:46:15 -0700106 */
107
Jing Huang5fbe25c2010-10-18 17:17:23 -0700108/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700109 * IOC state machine definitions/declarations
Jing Huang7725ccf2009-09-23 17:46:15 -0700110 */
111enum ioc_event {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700112 IOC_E_RESET = 1, /* IOC reset request */
113 IOC_E_ENABLE = 2, /* IOC enable request */
114 IOC_E_DISABLE = 3, /* IOC disable request */
115 IOC_E_DETACH = 4, /* driver detach cleanup */
116 IOC_E_ENABLED = 5, /* f/w enabled */
117 IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
118 IOC_E_DISABLED = 7, /* f/w disabled */
119 IOC_E_FAILED = 8, /* failure notice by iocpf sm */
120 IOC_E_HBFAIL = 9, /* heartbeat failure */
121 IOC_E_HWERROR = 10, /* hardware error interrupt */
122 IOC_E_TIMEOUT = 11, /* timeout */
Jing Huang7725ccf2009-09-23 17:46:15 -0700123};
124
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700125bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700126bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700127bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
128bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
129bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
130bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700131bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700132bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
133bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
134
135static struct bfa_sm_table_s ioc_sm_table[] = {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700136 {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
Jing Huang7725ccf2009-09-23 17:46:15 -0700137 {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700138 {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
Jing Huang7725ccf2009-09-23 17:46:15 -0700139 {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
140 {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
141 {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700142 {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
Jing Huang7725ccf2009-09-23 17:46:15 -0700143 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
144 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
145};
146
Jing Huang5fbe25c2010-10-18 17:17:23 -0700147/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700148 * IOCPF state machine definitions/declarations
149 */
150
151#define bfa_iocpf_timer_start(__ioc) \
152 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
153 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
154#define bfa_iocpf_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
155
156#define bfa_iocpf_recovery_timer_start(__ioc) \
157 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
158 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV_RECOVER)
159
160#define bfa_sem_timer_start(__ioc) \
161 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer, \
162 bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
163#define bfa_sem_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->sem_timer)
164
165/*
166 * Forward declareations for iocpf state machine
167 */
168static void bfa_iocpf_enable(struct bfa_ioc_s *ioc);
169static void bfa_iocpf_disable(struct bfa_ioc_s *ioc);
170static void bfa_iocpf_fail(struct bfa_ioc_s *ioc);
171static void bfa_iocpf_initfail(struct bfa_ioc_s *ioc);
172static void bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc);
173static void bfa_iocpf_stop(struct bfa_ioc_s *ioc);
174static void bfa_iocpf_timeout(void *ioc_arg);
175static void bfa_iocpf_sem_timeout(void *ioc_arg);
176
Jing Huang5fbe25c2010-10-18 17:17:23 -0700177/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700178 * IOCPF state machine events
179 */
180enum iocpf_event {
181 IOCPF_E_ENABLE = 1, /* IOCPF enable request */
182 IOCPF_E_DISABLE = 2, /* IOCPF disable request */
183 IOCPF_E_STOP = 3, /* stop on driver detach */
184 IOCPF_E_FWREADY = 4, /* f/w initialization done */
185 IOCPF_E_FWRSP_ENABLE = 5, /* enable f/w response */
186 IOCPF_E_FWRSP_DISABLE = 6, /* disable f/w response */
187 IOCPF_E_FAIL = 7, /* failure notice by ioc sm */
188 IOCPF_E_INITFAIL = 8, /* init fail notice by ioc sm */
189 IOCPF_E_GETATTRFAIL = 9, /* init fail notice by ioc sm */
190 IOCPF_E_SEMLOCKED = 10, /* h/w semaphore is locked */
191 IOCPF_E_TIMEOUT = 11, /* f/w response timeout */
192};
193
Jing Huang5fbe25c2010-10-18 17:17:23 -0700194/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700195 * IOCPF states
196 */
197enum bfa_iocpf_state {
198 BFA_IOCPF_RESET = 1, /* IOC is in reset state */
199 BFA_IOCPF_SEMWAIT = 2, /* Waiting for IOC h/w semaphore */
200 BFA_IOCPF_HWINIT = 3, /* IOC h/w is being initialized */
201 BFA_IOCPF_READY = 4, /* IOCPF is initialized */
202 BFA_IOCPF_INITFAIL = 5, /* IOCPF failed */
203 BFA_IOCPF_FAIL = 6, /* IOCPF failed */
204 BFA_IOCPF_DISABLING = 7, /* IOCPF is being disabled */
205 BFA_IOCPF_DISABLED = 8, /* IOCPF is disabled */
206 BFA_IOCPF_FWMISMATCH = 9, /* IOC f/w different from drivers */
207};
208
209bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
210bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
211bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
212bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
213bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
214bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
215bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
216bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
217bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
218bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
219bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
220
221static struct bfa_sm_table_s iocpf_sm_table[] = {
222 {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
223 {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
224 {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
225 {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
226 {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
227 {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
228 {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
229 {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
230 {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
231 {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
232 {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
233};
234
Jing Huang5fbe25c2010-10-18 17:17:23 -0700235/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700236 * IOC State Machine
237 */
238
Jing Huang5fbe25c2010-10-18 17:17:23 -0700239/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700240 * Beginning state. IOC uninit state.
241 */
242
243static void
244bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
245{
246}
247
Jing Huang5fbe25c2010-10-18 17:17:23 -0700248/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700249 * IOC is in uninit state.
250 */
251static void
252bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
253{
254 bfa_trc(ioc, event);
255
256 switch (event) {
257 case IOC_E_RESET:
258 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
259 break;
260
261 default:
262 bfa_sm_fault(ioc, event);
263 }
264}
Jing Huang5fbe25c2010-10-18 17:17:23 -0700265/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700266 * Reset entry actions -- initialize state machine
267 */
268static void
269bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
270{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700271 bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
Jing Huang7725ccf2009-09-23 17:46:15 -0700272}
273
Jing Huang5fbe25c2010-10-18 17:17:23 -0700274/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700275 * IOC is in reset state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700276 */
277static void
278bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
279{
280 bfa_trc(ioc, event);
281
282 switch (event) {
283 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700284 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
285 break;
286
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700287 case IOC_E_DISABLE:
288 bfa_ioc_disable_comp(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700289 break;
290
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700291 case IOC_E_DETACH:
292 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700293 break;
294
295 default:
296 bfa_sm_fault(ioc, event);
297 }
298}
299
300
301static void
302bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
303{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700304 bfa_iocpf_enable(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700305}
306
Jing Huang5fbe25c2010-10-18 17:17:23 -0700307/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700308 * Host IOC function is being enabled, awaiting response from firmware.
309 * Semaphore is acquired.
310 */
311static void
312bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
313{
314 bfa_trc(ioc, event);
315
316 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700317 case IOC_E_ENABLED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700318 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
319 break;
320
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700321 case IOC_E_FAILED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700322 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
323 break;
324
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700325 case IOC_E_HWERROR:
326 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
327 bfa_iocpf_initfail(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700328 break;
329
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700330 case IOC_E_DISABLE:
331 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
332 break;
333
334 case IOC_E_DETACH:
335 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
336 bfa_iocpf_stop(ioc);
337 break;
338
339 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700340 break;
341
342 default:
343 bfa_sm_fault(ioc, event);
344 }
345}
346
347
348static void
349bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
350{
351 bfa_ioc_timer_start(ioc);
352 bfa_ioc_send_getattr(ioc);
353}
354
Jing Huang5fbe25c2010-10-18 17:17:23 -0700355/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700356 * IOC configuration in progress. Timer is active.
357 */
358static void
359bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
360{
361 bfa_trc(ioc, event);
362
363 switch (event) {
364 case IOC_E_FWRSP_GETATTR:
365 bfa_ioc_timer_stop(ioc);
Jing Huang07b28382010-07-08 19:59:24 -0700366 bfa_ioc_check_attr_wwns(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700367 bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
368 break;
369
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700370 case IOC_E_FAILED:
371 bfa_ioc_timer_stop(ioc);
372 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
373 break;
374
Jing Huang7725ccf2009-09-23 17:46:15 -0700375 case IOC_E_HWERROR:
376 bfa_ioc_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700377 /* fall through */
Jing Huang7725ccf2009-09-23 17:46:15 -0700378
379 case IOC_E_TIMEOUT:
380 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700381 bfa_iocpf_getattrfail(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700382 break;
383
384 case IOC_E_DISABLE:
385 bfa_ioc_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700386 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
387 break;
388
389 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700390 break;
391
392 default:
393 bfa_sm_fault(ioc, event);
394 }
395}
396
397
398static void
399bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
400{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700401 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
402
Jing Huang7725ccf2009-09-23 17:46:15 -0700403 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
404 bfa_ioc_hb_monitor(ioc);
Jing Huang88166242010-12-09 17:11:53 -0800405 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700406}
407
408static void
409bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
410{
411 bfa_trc(ioc, event);
412
413 switch (event) {
414 case IOC_E_ENABLE:
415 break;
416
417 case IOC_E_DISABLE:
418 bfa_ioc_hb_stop(ioc);
419 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
420 break;
421
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700422 case IOC_E_FAILED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700423 bfa_ioc_hb_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700424 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
425 break;
426
427 case IOC_E_HWERROR:
428 bfa_ioc_hb_stop(ioc);
429 /* !!! fall through !!! */
Jing Huang7725ccf2009-09-23 17:46:15 -0700430
431 case IOC_E_HBFAIL:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700432 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
433 bfa_iocpf_fail(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700434 break;
435
436 default:
437 bfa_sm_fault(ioc, event);
438 }
439}
440
441
442static void
443bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
444{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700445 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
446 bfa_iocpf_disable(ioc);
Jing Huang88166242010-12-09 17:11:53 -0800447 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700448}
449
Jing Huang5fbe25c2010-10-18 17:17:23 -0700450/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700451 * IOC is being disabled
452 */
453static void
454bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
455{
456 bfa_trc(ioc, event);
457
458 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700459 case IOC_E_DISABLED:
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800460 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
461 break;
462
463 case IOC_E_HWERROR:
Jing Huang7725ccf2009-09-23 17:46:15 -0700464 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700465 * No state change. Will move to disabled state
466 * after iocpf sm completes failure processing and
467 * moves to disabled state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700468 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700469 bfa_iocpf_fail(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700470 break;
471
472 default:
473 bfa_sm_fault(ioc, event);
474 }
475}
476
Jing Huang5fbe25c2010-10-18 17:17:23 -0700477/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700478 * IOC disable completion entry.
479 */
480static void
481bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
482{
483 bfa_ioc_disable_comp(ioc);
484}
485
486static void
487bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
488{
489 bfa_trc(ioc, event);
490
491 switch (event) {
492 case IOC_E_ENABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700493 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700494 break;
495
496 case IOC_E_DISABLE:
497 ioc->cbfn->disable_cbfn(ioc->bfa);
498 break;
499
Jing Huang7725ccf2009-09-23 17:46:15 -0700500 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700501 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
502 bfa_iocpf_stop(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700503 break;
504
505 default:
506 bfa_sm_fault(ioc, event);
507 }
508}
509
510
511static void
512bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc)
513{
514 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700515}
516
Jing Huang5fbe25c2010-10-18 17:17:23 -0700517/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700518 * Hardware initialization failed.
519 */
520static void
521bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
522{
523 bfa_trc(ioc, event);
524
525 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700526 case IOC_E_ENABLED:
527 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
528 break;
529
530 case IOC_E_FAILED:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700531 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700532 * Initialization failure during iocpf init retry.
533 */
534 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
535 break;
536
Jing Huang7725ccf2009-09-23 17:46:15 -0700537 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700538 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700539 break;
540
541 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700542 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
543 bfa_iocpf_stop(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700544 break;
545
546 default:
547 bfa_sm_fault(ioc, event);
548 }
549}
550
551
552static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700553bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -0700554{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700555 struct list_head *qe;
556 struct bfa_ioc_hbfail_notify_s *notify;
557 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Jing Huang7725ccf2009-09-23 17:46:15 -0700558
Jing Huang5fbe25c2010-10-18 17:17:23 -0700559 /*
Jing Huang7725ccf2009-09-23 17:46:15 -0700560 * Notify driver and common modules registered for notification.
561 */
562 ioc->cbfn->hbfail_cbfn(ioc->bfa);
563 list_for_each(qe, &ioc->hb_notify_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700564 notify = (struct bfa_ioc_hbfail_notify_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -0700565 notify->cbfn(notify->cbarg);
566 }
567
Jing Huang88166242010-12-09 17:11:53 -0800568 BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700569 "Heart Beat of IOC has failed\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700570}
571
Jing Huang5fbe25c2010-10-18 17:17:23 -0700572/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700573 * IOC failure.
Jing Huang7725ccf2009-09-23 17:46:15 -0700574 */
575static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700576bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700577{
578 bfa_trc(ioc, event);
579
580 switch (event) {
581
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700582 case IOC_E_FAILED:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700583 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700584 * Initialization failure during iocpf recovery.
585 * !!! Fall through !!!
586 */
Jing Huang7725ccf2009-09-23 17:46:15 -0700587 case IOC_E_ENABLE:
588 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
589 break;
590
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700591 case IOC_E_ENABLED:
592 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
593 break;
594
Jing Huang7725ccf2009-09-23 17:46:15 -0700595 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700596 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700597 break;
598
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800599 case IOC_E_HWERROR:
600 /*
601 * HB failure notification, ignore.
602 */
603 break;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700604 default:
605 bfa_sm_fault(ioc, event);
606 }
607}
608
609
610
Jing Huang5fbe25c2010-10-18 17:17:23 -0700611/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700612 * IOCPF State Machine
613 */
614
615
Jing Huang5fbe25c2010-10-18 17:17:23 -0700616/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700617 * Reset entry actions -- initialize state machine
618 */
619static void
620bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
621{
622 iocpf->retry_count = 0;
623 iocpf->auto_recover = bfa_auto_recover;
624}
625
Jing Huang5fbe25c2010-10-18 17:17:23 -0700626/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700627 * Beginning state. IOC is in reset state.
628 */
629static void
630bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
631{
632 struct bfa_ioc_s *ioc = iocpf->ioc;
633
634 bfa_trc(ioc, event);
635
636 switch (event) {
637 case IOCPF_E_ENABLE:
638 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
639 break;
640
641 case IOCPF_E_STOP:
642 break;
643
644 default:
645 bfa_sm_fault(ioc, event);
646 }
647}
648
Jing Huang5fbe25c2010-10-18 17:17:23 -0700649/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700650 * Semaphore should be acquired for version check.
651 */
652static void
653bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
654{
655 bfa_ioc_hw_sem_get(iocpf->ioc);
656}
657
Jing Huang5fbe25c2010-10-18 17:17:23 -0700658/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700659 * Awaiting h/w semaphore to continue with version check.
660 */
661static void
662bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
663{
664 struct bfa_ioc_s *ioc = iocpf->ioc;
665
666 bfa_trc(ioc, event);
667
668 switch (event) {
669 case IOCPF_E_SEMLOCKED:
670 if (bfa_ioc_firmware_lock(ioc)) {
671 iocpf->retry_count = 0;
672 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
673 } else {
674 bfa_ioc_hw_sem_release(ioc);
675 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
676 }
677 break;
678
679 case IOCPF_E_DISABLE:
680 bfa_ioc_hw_sem_get_cancel(ioc);
681 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
682 bfa_ioc_pf_disabled(ioc);
683 break;
684
685 case IOCPF_E_STOP:
686 bfa_ioc_hw_sem_get_cancel(ioc);
687 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
688 break;
689
690 default:
691 bfa_sm_fault(ioc, event);
692 }
693}
694
Jing Huang5fbe25c2010-10-18 17:17:23 -0700695/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700696 * Notify enable completion callback.
697 */
698static void
699bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
700{
701 /*
702 * Call only the first time sm enters fwmismatch state.
703 */
704 if (iocpf->retry_count == 0)
705 bfa_ioc_pf_fwmismatch(iocpf->ioc);
706
707 iocpf->retry_count++;
708 bfa_iocpf_timer_start(iocpf->ioc);
709}
710
Jing Huang5fbe25c2010-10-18 17:17:23 -0700711/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700712 * Awaiting firmware version match.
713 */
714static void
715bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
716{
717 struct bfa_ioc_s *ioc = iocpf->ioc;
718
719 bfa_trc(ioc, event);
720
721 switch (event) {
722 case IOCPF_E_TIMEOUT:
723 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
724 break;
725
726 case IOCPF_E_DISABLE:
727 bfa_iocpf_timer_stop(ioc);
728 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
729 bfa_ioc_pf_disabled(ioc);
730 break;
731
732 case IOCPF_E_STOP:
733 bfa_iocpf_timer_stop(ioc);
734 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
735 break;
736
737 default:
738 bfa_sm_fault(ioc, event);
739 }
740}
741
Jing Huang5fbe25c2010-10-18 17:17:23 -0700742/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700743 * Request for semaphore.
744 */
745static void
746bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
747{
748 bfa_ioc_hw_sem_get(iocpf->ioc);
749}
750
Jing Huang5fbe25c2010-10-18 17:17:23 -0700751/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700752 * Awaiting semaphore for h/w initialzation.
753 */
754static void
755bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
756{
757 struct bfa_ioc_s *ioc = iocpf->ioc;
758
759 bfa_trc(ioc, event);
760
761 switch (event) {
762 case IOCPF_E_SEMLOCKED:
763 iocpf->retry_count = 0;
764 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
765 break;
766
767 case IOCPF_E_DISABLE:
768 bfa_ioc_hw_sem_get_cancel(ioc);
769 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
770 break;
771
772 default:
773 bfa_sm_fault(ioc, event);
774 }
775}
776
777
778static void
779bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
780{
781 bfa_iocpf_timer_start(iocpf->ioc);
782 bfa_ioc_reset(iocpf->ioc, BFA_FALSE);
783}
784
Jing Huang5fbe25c2010-10-18 17:17:23 -0700785/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700786 * Hardware is being initialized. Interrupts are enabled.
787 * Holding hardware semaphore lock.
788 */
789static void
790bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
791{
792 struct bfa_ioc_s *ioc = iocpf->ioc;
793
794 bfa_trc(ioc, event);
795
796 switch (event) {
797 case IOCPF_E_FWREADY:
798 bfa_iocpf_timer_stop(ioc);
799 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
800 break;
801
802 case IOCPF_E_INITFAIL:
803 bfa_iocpf_timer_stop(ioc);
804 /*
805 * !!! fall through !!!
806 */
807
808 case IOCPF_E_TIMEOUT:
809 iocpf->retry_count++;
810 if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
811 bfa_iocpf_timer_start(ioc);
812 bfa_ioc_reset(ioc, BFA_TRUE);
813 break;
814 }
815
816 bfa_ioc_hw_sem_release(ioc);
817 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
818
819 if (event == IOCPF_E_TIMEOUT)
820 bfa_ioc_pf_failed(ioc);
821 break;
822
823 case IOCPF_E_DISABLE:
824 bfa_ioc_hw_sem_release(ioc);
825 bfa_iocpf_timer_stop(ioc);
826 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
827 break;
828
829 default:
830 bfa_sm_fault(ioc, event);
831 }
832}
833
834
835static void
836bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
837{
838 bfa_iocpf_timer_start(iocpf->ioc);
839 bfa_ioc_send_enable(iocpf->ioc);
840}
841
Jing Huang5fbe25c2010-10-18 17:17:23 -0700842/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700843 * Host IOC function is being enabled, awaiting response from firmware.
844 * Semaphore is acquired.
845 */
846static void
847bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
848{
849 struct bfa_ioc_s *ioc = iocpf->ioc;
850
851 bfa_trc(ioc, event);
852
853 switch (event) {
854 case IOCPF_E_FWRSP_ENABLE:
855 bfa_iocpf_timer_stop(ioc);
856 bfa_ioc_hw_sem_release(ioc);
857 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
858 break;
859
860 case IOCPF_E_INITFAIL:
861 bfa_iocpf_timer_stop(ioc);
862 /*
863 * !!! fall through !!!
864 */
865
866 case IOCPF_E_TIMEOUT:
867 iocpf->retry_count++;
868 if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) {
Jing Huang53440262010-10-18 17:12:29 -0700869 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700870 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
871 break;
872 }
873
874 bfa_ioc_hw_sem_release(ioc);
875 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
876
877 if (event == IOCPF_E_TIMEOUT)
878 bfa_ioc_pf_failed(ioc);
879 break;
880
881 case IOCPF_E_DISABLE:
882 bfa_iocpf_timer_stop(ioc);
883 bfa_ioc_hw_sem_release(ioc);
884 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
885 break;
886
887 case IOCPF_E_FWREADY:
888 bfa_ioc_send_enable(ioc);
889 break;
890
891 default:
892 bfa_sm_fault(ioc, event);
893 }
894}
895
896
897
898static void
899bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
900{
901 bfa_ioc_pf_enabled(iocpf->ioc);
902}
903
904static void
905bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
906{
907 struct bfa_ioc_s *ioc = iocpf->ioc;
908
909 bfa_trc(ioc, event);
910
911 switch (event) {
912 case IOCPF_E_DISABLE:
913 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
914 break;
915
916 case IOCPF_E_GETATTRFAIL:
917 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
918 break;
919
920 case IOCPF_E_FAIL:
921 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
922 break;
923
924 case IOCPF_E_FWREADY:
925 if (bfa_ioc_is_operational(ioc))
926 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
927 else
928 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
929
930 bfa_ioc_pf_failed(ioc);
931 break;
932
933 default:
934 bfa_sm_fault(ioc, event);
935 }
936}
937
938
939static void
940bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
941{
942 bfa_iocpf_timer_start(iocpf->ioc);
943 bfa_ioc_send_disable(iocpf->ioc);
944}
945
Jing Huang5fbe25c2010-10-18 17:17:23 -0700946/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700947 * IOC is being disabled
948 */
949static void
950bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
951{
952 struct bfa_ioc_s *ioc = iocpf->ioc;
953
954 bfa_trc(ioc, event);
955
956 switch (event) {
957 case IOCPF_E_FWRSP_DISABLE:
958 case IOCPF_E_FWREADY:
959 bfa_iocpf_timer_stop(ioc);
960 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
961 break;
962
963 case IOCPF_E_FAIL:
964 bfa_iocpf_timer_stop(ioc);
965 /*
966 * !!! fall through !!!
967 */
968
969 case IOCPF_E_TIMEOUT:
Jing Huang53440262010-10-18 17:12:29 -0700970 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700971 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
972 break;
973
974 case IOCPF_E_FWRSP_ENABLE:
975 break;
976
977 default:
978 bfa_sm_fault(ioc, event);
979 }
980}
981
Jing Huang5fbe25c2010-10-18 17:17:23 -0700982/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700983 * IOC disable completion entry.
984 */
985static void
986bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
987{
988 bfa_ioc_pf_disabled(iocpf->ioc);
989}
990
991static void
992bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
993{
994 struct bfa_ioc_s *ioc = iocpf->ioc;
995
996 bfa_trc(ioc, event);
997
998 switch (event) {
999 case IOCPF_E_ENABLE:
1000 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1001 break;
1002
1003 case IOCPF_E_STOP:
1004 bfa_ioc_firmware_unlock(ioc);
1005 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1006 break;
1007
1008 default:
1009 bfa_sm_fault(ioc, event);
1010 }
1011}
1012
1013
1014static void
1015bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
1016{
1017 bfa_iocpf_timer_start(iocpf->ioc);
1018}
1019
Jing Huang5fbe25c2010-10-18 17:17:23 -07001020/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001021 * Hardware initialization failed.
1022 */
1023static void
1024bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1025{
1026 struct bfa_ioc_s *ioc = iocpf->ioc;
1027
1028 bfa_trc(ioc, event);
1029
1030 switch (event) {
1031 case IOCPF_E_DISABLE:
1032 bfa_iocpf_timer_stop(ioc);
1033 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1034 break;
1035
1036 case IOCPF_E_STOP:
1037 bfa_iocpf_timer_stop(ioc);
1038 bfa_ioc_firmware_unlock(ioc);
1039 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1040 break;
1041
1042 case IOCPF_E_TIMEOUT:
1043 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1044 break;
1045
1046 default:
1047 bfa_sm_fault(ioc, event);
1048 }
1049}
1050
1051
1052static void
1053bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
1054{
Jing Huang5fbe25c2010-10-18 17:17:23 -07001055 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001056 * Mark IOC as failed in hardware and stop firmware.
1057 */
1058 bfa_ioc_lpu_stop(iocpf->ioc);
Jing Huang53440262010-10-18 17:12:29 -07001059 writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001060
Jing Huang5fbe25c2010-10-18 17:17:23 -07001061 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001062 * Notify other functions on HB failure.
1063 */
1064 bfa_ioc_notify_hbfail(iocpf->ioc);
1065
Jing Huang5fbe25c2010-10-18 17:17:23 -07001066 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001067 * Flush any queued up mailbox requests.
1068 */
1069 bfa_ioc_mbox_hbfail(iocpf->ioc);
1070
1071 if (iocpf->auto_recover)
1072 bfa_iocpf_recovery_timer_start(iocpf->ioc);
1073}
1074
Jing Huang5fbe25c2010-10-18 17:17:23 -07001075/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001076 * IOC is in failed state.
1077 */
1078static void
1079bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1080{
1081 struct bfa_ioc_s *ioc = iocpf->ioc;
1082
1083 bfa_trc(ioc, event);
1084
1085 switch (event) {
1086 case IOCPF_E_DISABLE:
1087 if (iocpf->auto_recover)
1088 bfa_iocpf_timer_stop(ioc);
1089 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1090 break;
1091
1092 case IOCPF_E_TIMEOUT:
1093 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1094 break;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001095
Jing Huang7725ccf2009-09-23 17:46:15 -07001096 default:
1097 bfa_sm_fault(ioc, event);
1098 }
1099}
1100
1101
1102
Jing Huang5fbe25c2010-10-18 17:17:23 -07001103/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001104 * hal_ioc_pvt BFA IOC private functions
Jing Huang7725ccf2009-09-23 17:46:15 -07001105 */
1106
1107static void
1108bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
1109{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001110 struct list_head *qe;
1111 struct bfa_ioc_hbfail_notify_s *notify;
Jing Huang7725ccf2009-09-23 17:46:15 -07001112
1113 ioc->cbfn->disable_cbfn(ioc->bfa);
1114
Jing Huang5fbe25c2010-10-18 17:17:23 -07001115 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001116 * Notify common modules registered for notification.
1117 */
1118 list_for_each(qe, &ioc->hb_notify_q) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001119 notify = (struct bfa_ioc_hbfail_notify_s *) qe;
Jing Huang7725ccf2009-09-23 17:46:15 -07001120 notify->cbfn(notify->cbarg);
1121 }
1122}
1123
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001124bfa_boolean_t
Jing Huang53440262010-10-18 17:12:29 -07001125bfa_ioc_sem_get(void __iomem *sem_reg)
Jing Huang7725ccf2009-09-23 17:46:15 -07001126{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001127 u32 r32;
1128 int cnt = 0;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001129#define BFA_SEM_SPINCNT 3000
Jing Huang7725ccf2009-09-23 17:46:15 -07001130
Jing Huang53440262010-10-18 17:12:29 -07001131 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001132
1133 while (r32 && (cnt < BFA_SEM_SPINCNT)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001134 cnt++;
Jing Huang6a18b162010-10-18 17:08:54 -07001135 udelay(2);
Jing Huang53440262010-10-18 17:12:29 -07001136 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001137 }
1138
1139 if (r32 == 0)
1140 return BFA_TRUE;
1141
Jing Huang7725ccf2009-09-23 17:46:15 -07001142 bfa_assert(cnt < BFA_SEM_SPINCNT);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001143 return BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001144}
1145
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001146void
Jing Huang53440262010-10-18 17:12:29 -07001147bfa_ioc_sem_release(void __iomem *sem_reg)
Jing Huang7725ccf2009-09-23 17:46:15 -07001148{
Jing Huang53440262010-10-18 17:12:29 -07001149 writel(1, sem_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001150}
1151
1152static void
1153bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
1154{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001155 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001156
Jing Huang5fbe25c2010-10-18 17:17:23 -07001157 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001158 * First read to the semaphore register will return 0, subsequent reads
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001159 * will return 1. Semaphore is released by writing 1 to the register
Jing Huang7725ccf2009-09-23 17:46:15 -07001160 */
Jing Huang53440262010-10-18 17:12:29 -07001161 r32 = readl(ioc->ioc_regs.ioc_sem_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001162 if (r32 == 0) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001163 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
Jing Huang7725ccf2009-09-23 17:46:15 -07001164 return;
1165 }
1166
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001167 bfa_sem_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001168}
1169
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001170void
Jing Huang7725ccf2009-09-23 17:46:15 -07001171bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc)
1172{
Jing Huang53440262010-10-18 17:12:29 -07001173 writel(1, ioc->ioc_regs.ioc_sem_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001174}
1175
1176static void
1177bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc)
1178{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001179 bfa_sem_timer_stop(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001180}
1181
Jing Huang5fbe25c2010-10-18 17:17:23 -07001182/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001183 * Initialize LPU local memory (aka secondary memory / SRAM)
1184 */
1185static void
1186bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
1187{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001188 u32 pss_ctl;
1189 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001190#define PSS_LMEM_INIT_TIME 10000
1191
Jing Huang53440262010-10-18 17:12:29 -07001192 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001193 pss_ctl &= ~__PSS_LMEM_RESET;
1194 pss_ctl |= __PSS_LMEM_INIT_EN;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001195
1196 /*
1197 * i2c workaround 12.5khz clock
1198 */
1199 pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
Jing Huang53440262010-10-18 17:12:29 -07001200 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001201
Jing Huang5fbe25c2010-10-18 17:17:23 -07001202 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001203 * wait for memory initialization to be complete
1204 */
1205 i = 0;
1206 do {
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 i++;
1209 } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1210
Jing Huang5fbe25c2010-10-18 17:17:23 -07001211 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001212 * If memory initialization is not successful, IOC timeout will catch
1213 * such failures.
1214 */
1215 bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE);
1216 bfa_trc(ioc, pss_ctl);
1217
1218 pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
Jing Huang53440262010-10-18 17:12:29 -07001219 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001220}
1221
1222static void
1223bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
1224{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001225 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001226
Jing Huang5fbe25c2010-10-18 17:17:23 -07001227 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001228 * Take processor out of reset.
1229 */
Jing Huang53440262010-10-18 17:12:29 -07001230 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001231 pss_ctl &= ~__PSS_LPU0_RESET;
1232
Jing Huang53440262010-10-18 17:12:29 -07001233 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001234}
1235
1236static void
1237bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
1238{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001239 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001240
Jing Huang5fbe25c2010-10-18 17:17:23 -07001241 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001242 * Put processors in reset.
1243 */
Jing Huang53440262010-10-18 17:12:29 -07001244 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001245 pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1246
Jing Huang53440262010-10-18 17:12:29 -07001247 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001248}
1249
Jing Huang5fbe25c2010-10-18 17:17:23 -07001250/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001251 * Get driver and firmware versions.
1252 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001253void
Jing Huang7725ccf2009-09-23 17:46:15 -07001254bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1255{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001256 u32 pgnum, pgoff;
1257 u32 loff = 0;
1258 int i;
1259 u32 *fwsig = (u32 *) fwhdr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001260
1261 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
1262 pgoff = bfa_ioc_smem_pgoff(ioc, loff);
Jing Huang53440262010-10-18 17:12:29 -07001263 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001264
1265 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
1266 i++) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001267 fwsig[i] =
1268 bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001269 loff += sizeof(u32);
1270 }
1271}
1272
Jing Huang5fbe25c2010-10-18 17:17:23 -07001273/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001274 * Returns TRUE if same.
1275 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001276bfa_boolean_t
Jing Huang7725ccf2009-09-23 17:46:15 -07001277bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1278{
1279 struct bfi_ioc_image_hdr_s *drv_fwhdr;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001280 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001281
Jing Huang293f82d2010-07-08 19:45:20 -07001282 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001283 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001284
1285 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1286 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
1287 bfa_trc(ioc, i);
1288 bfa_trc(ioc, fwhdr->md5sum[i]);
1289 bfa_trc(ioc, drv_fwhdr->md5sum[i]);
1290 return BFA_FALSE;
1291 }
1292 }
1293
1294 bfa_trc(ioc, fwhdr->md5sum[0]);
1295 return BFA_TRUE;
1296}
1297
Jing Huang5fbe25c2010-10-18 17:17:23 -07001298/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001299 * Return true if current running version is valid. Firmware signature and
1300 * execution context (driver/bios) must match.
1301 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001302static bfa_boolean_t
1303bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001304{
1305 struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
1306
Jing Huang5fbe25c2010-10-18 17:17:23 -07001307 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001308 * If bios/efi boot (flash based) -- return true
1309 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001310 if (bfa_ioc_is_bios_optrom(ioc))
Jing Huang7725ccf2009-09-23 17:46:15 -07001311 return BFA_TRUE;
1312
1313 bfa_ioc_fwver_get(ioc, &fwhdr);
Jing Huang293f82d2010-07-08 19:45:20 -07001314 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001315 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001316
1317 if (fwhdr.signature != drv_fwhdr->signature) {
1318 bfa_trc(ioc, fwhdr.signature);
1319 bfa_trc(ioc, drv_fwhdr->signature);
1320 return BFA_FALSE;
1321 }
1322
Jing Huang53440262010-10-18 17:12:29 -07001323 if (swab32(fwhdr.param) != boot_env) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001324 bfa_trc(ioc, fwhdr.param);
1325 bfa_trc(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001326 return BFA_FALSE;
1327 }
1328
1329 return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1330}
1331
Jing Huang5fbe25c2010-10-18 17:17:23 -07001332/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001333 * Conditionally flush any pending message from firmware at start.
1334 */
1335static void
1336bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1337{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001338 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001339
Jing Huang53440262010-10-18 17:12:29 -07001340 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001341 if (r32)
Jing Huang53440262010-10-18 17:12:29 -07001342 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001343}
1344
1345
1346static void
1347bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1348{
1349 enum bfi_ioc_state ioc_fwstate;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001350 bfa_boolean_t fwvalid;
1351 u32 boot_type;
1352 u32 boot_env;
Jing Huang7725ccf2009-09-23 17:46:15 -07001353
Jing Huang53440262010-10-18 17:12:29 -07001354 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07001355
1356 if (force)
1357 ioc_fwstate = BFI_IOC_UNINIT;
1358
1359 bfa_trc(ioc, ioc_fwstate);
1360
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001361 boot_type = BFI_BOOT_TYPE_NORMAL;
1362 boot_env = BFI_BOOT_LOADER_OS;
1363
Jing Huang5fbe25c2010-10-18 17:17:23 -07001364 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001365 * Flash based firmware boot BIOS env.
1366 */
1367 if (bfa_ioc_is_bios_optrom(ioc)) {
1368 boot_type = BFI_BOOT_TYPE_FLASH;
1369 boot_env = BFI_BOOT_LOADER_BIOS;
1370 }
1371
Jing Huang5fbe25c2010-10-18 17:17:23 -07001372 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001373 * Flash based firmware boot UEFI env.
1374 */
1375 if (bfa_ioc_is_uefi(ioc)) {
1376 boot_type = BFI_BOOT_TYPE_FLASH;
1377 boot_env = BFI_BOOT_LOADER_UEFI;
1378 }
1379
Jing Huang5fbe25c2010-10-18 17:17:23 -07001380 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001381 * check if firmware is valid
1382 */
1383 fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001384 BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001385
1386 if (!fwvalid) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001387 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001388 return;
1389 }
1390
Jing Huang5fbe25c2010-10-18 17:17:23 -07001391 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001392 * If hardware initialization is in progress (initialized by other IOC),
1393 * just wait for an initialization completion interrupt.
1394 */
1395 if (ioc_fwstate == BFI_IOC_INITING) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001396 ioc->cbfn->reset_cbfn(ioc->bfa);
1397 return;
1398 }
1399
Jing Huang5fbe25c2010-10-18 17:17:23 -07001400 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001401 * If IOC function is disabled and firmware version is same,
1402 * just re-enable IOC.
Jing Huang07b28382010-07-08 19:59:24 -07001403 *
1404 * If option rom, IOC must not be in operational state. With
1405 * convergence, IOC will be in operational state when 2nd driver
1406 * is loaded.
Jing Huang7725ccf2009-09-23 17:46:15 -07001407 */
Jing Huang07b28382010-07-08 19:59:24 -07001408 if (ioc_fwstate == BFI_IOC_DISABLED ||
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001409 (!bfa_ioc_is_bios_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001410
Jing Huang5fbe25c2010-10-18 17:17:23 -07001411 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001412 * When using MSI-X any pending firmware ready event should
1413 * be flushed. Otherwise MSI-X interrupts are not delivered.
1414 */
1415 bfa_ioc_msgflush(ioc);
1416 ioc->cbfn->reset_cbfn(ioc->bfa);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001417 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001418 return;
1419 }
1420
Jing Huang5fbe25c2010-10-18 17:17:23 -07001421 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001422 * Initialize the h/w for any other states.
1423 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001424 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001425}
1426
1427static void
1428bfa_ioc_timeout(void *ioc_arg)
1429{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001430 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -07001431
1432 bfa_trc(ioc, 0);
1433 bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1434}
1435
1436void
1437bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1438{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001439 u32 *msgp = (u32 *) ioc_msg;
1440 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001441
1442 bfa_trc(ioc, msgp[0]);
1443 bfa_trc(ioc, len);
1444
1445 bfa_assert(len <= BFI_IOC_MSGLEN_MAX);
1446
1447 /*
1448 * first write msg to mailbox registers
1449 */
1450 for (i = 0; i < len / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001451 writel(cpu_to_le32(msgp[i]),
1452 ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001453
1454 for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001455 writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001456
1457 /*
1458 * write 1 to mailbox CMD to trigger LPU event
1459 */
Jing Huang53440262010-10-18 17:12:29 -07001460 writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1461 (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001462}
1463
1464static void
1465bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1466{
1467 struct bfi_ioc_ctrl_req_s enable_req;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001468 struct bfa_timeval_s tv;
Jing Huang7725ccf2009-09-23 17:46:15 -07001469
1470 bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1471 bfa_ioc_portid(ioc));
1472 enable_req.ioc_class = ioc->ioc_mc;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001473 bfa_os_gettimeofday(&tv);
Jing Huangba816ea2010-10-18 17:10:50 -07001474 enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
Jing Huang7725ccf2009-09-23 17:46:15 -07001475 bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1476}
1477
1478static void
1479bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1480{
1481 struct bfi_ioc_ctrl_req_s disable_req;
1482
1483 bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1484 bfa_ioc_portid(ioc));
1485 bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1486}
1487
1488static void
1489bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1490{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001491 struct bfi_ioc_getattr_req_s attr_req;
Jing Huang7725ccf2009-09-23 17:46:15 -07001492
1493 bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1494 bfa_ioc_portid(ioc));
1495 bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1496 bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1497}
1498
1499static void
1500bfa_ioc_hb_check(void *cbarg)
1501{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001502 struct bfa_ioc_s *ioc = cbarg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001503 u32 hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001504
Jing Huang53440262010-10-18 17:12:29 -07001505 hb_count = readl(ioc->ioc_regs.heartbeat);
Jing Huang7725ccf2009-09-23 17:46:15 -07001506 if (ioc->hb_count == hb_count) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001507 printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count);
Jing Huang7725ccf2009-09-23 17:46:15 -07001508 bfa_ioc_recover(ioc);
1509 return;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001510 } else {
1511 ioc->hb_count = hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001512 }
1513
1514 bfa_ioc_mbox_poll(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001515 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001516}
1517
1518static void
1519bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1520{
Jing Huang53440262010-10-18 17:12:29 -07001521 ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001522 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001523}
1524
1525static void
1526bfa_ioc_hb_stop(struct bfa_ioc_s *ioc)
1527{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001528 bfa_hb_timer_stop(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001529}
1530
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001531
Jing Huang5fbe25c2010-10-18 17:17:23 -07001532/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001533 * Initiate a full firmware download.
Jing Huang7725ccf2009-09-23 17:46:15 -07001534 */
1535static void
1536bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001537 u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001538{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001539 u32 *fwimg;
1540 u32 pgnum, pgoff;
1541 u32 loff = 0;
1542 u32 chunkno = 0;
1543 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001544
Jing Huang5fbe25c2010-10-18 17:17:23 -07001545 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001546 * Initialize LMEM first before code download
1547 */
1548 bfa_ioc_lmem_init(ioc);
1549
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001550 bfa_trc(ioc, bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)));
1551 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
Jing Huang7725ccf2009-09-23 17:46:15 -07001552
1553 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
1554 pgoff = bfa_ioc_smem_pgoff(ioc, loff);
1555
Jing Huang53440262010-10-18 17:12:29 -07001556 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001557
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001558 for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001559
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001560 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1561 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001562 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001563 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
Jing Huang7725ccf2009-09-23 17:46:15 -07001564 }
1565
Jing Huang5fbe25c2010-10-18 17:17:23 -07001566 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001567 * write smem
1568 */
1569 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001570 fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
Jing Huang7725ccf2009-09-23 17:46:15 -07001571
1572 loff += sizeof(u32);
1573
Jing Huang5fbe25c2010-10-18 17:17:23 -07001574 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001575 * handle page offset wrap around
1576 */
1577 loff = PSS_SMEM_PGOFF(loff);
1578 if (loff == 0) {
1579 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001580 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001581 }
1582 }
1583
Jing Huang53440262010-10-18 17:12:29 -07001584 writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001585
1586 /*
1587 * Set boot type and boot param at the end.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001588 */
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001589 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_TYPE_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001590 swab32(boot_type));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001591 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_BOOT_LOADER_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001592 swab32(boot_env));
Jing Huang7725ccf2009-09-23 17:46:15 -07001593}
1594
1595static void
1596bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1597{
1598 bfa_ioc_hwinit(ioc, force);
1599}
1600
Jing Huang5fbe25c2010-10-18 17:17:23 -07001601/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001602 * Update BFA configuration from firmware configuration.
1603 */
1604static void
1605bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1606{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001607 struct bfi_ioc_attr_s *attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001608
Jing Huangba816ea2010-10-18 17:10:50 -07001609 attr->adapter_prop = be32_to_cpu(attr->adapter_prop);
1610 attr->card_type = be32_to_cpu(attr->card_type);
1611 attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
Jing Huang7725ccf2009-09-23 17:46:15 -07001612
1613 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1614}
1615
Jing Huang5fbe25c2010-10-18 17:17:23 -07001616/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001617 * Attach time initialization of mbox logic.
1618 */
1619static void
1620bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1621{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001622 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1623 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001624
1625 INIT_LIST_HEAD(&mod->cmd_q);
1626 for (mc = 0; mc < BFI_MC_MAX; mc++) {
1627 mod->mbhdlr[mc].cbfn = NULL;
1628 mod->mbhdlr[mc].cbarg = ioc->bfa;
1629 }
1630}
1631
Jing Huang5fbe25c2010-10-18 17:17:23 -07001632/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001633 * Mbox poll timer -- restarts any pending mailbox requests.
1634 */
1635static void
1636bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1637{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001638 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1639 struct bfa_mbox_cmd_s *cmd;
1640 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07001641
Jing Huang5fbe25c2010-10-18 17:17:23 -07001642 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001643 * If no command pending, do nothing
1644 */
1645 if (list_empty(&mod->cmd_q))
1646 return;
1647
Jing Huang5fbe25c2010-10-18 17:17:23 -07001648 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001649 * If previous command is not yet fetched by firmware, do nothing
1650 */
Jing Huang53440262010-10-18 17:12:29 -07001651 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001652 if (stat)
1653 return;
1654
Jing Huang5fbe25c2010-10-18 17:17:23 -07001655 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001656 * Enqueue command to firmware.
1657 */
1658 bfa_q_deq(&mod->cmd_q, &cmd);
1659 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1660}
1661
Jing Huang5fbe25c2010-10-18 17:17:23 -07001662/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001663 * Cleanup any pending requests.
1664 */
1665static void
1666bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
1667{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001668 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1669 struct bfa_mbox_cmd_s *cmd;
Jing Huang7725ccf2009-09-23 17:46:15 -07001670
1671 while (!list_empty(&mod->cmd_q))
1672 bfa_q_deq(&mod->cmd_q, &cmd);
1673}
1674
Jing Huang5fbe25c2010-10-18 17:17:23 -07001675/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001676 * Read data from SMEM to host through PCI memmap
1677 *
1678 * @param[in] ioc memory for IOC
1679 * @param[in] tbuf app memory to store data from smem
1680 * @param[in] soff smem offset
1681 * @param[in] sz size of smem in bytes
Jing Huang7725ccf2009-09-23 17:46:15 -07001682 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001683static bfa_status_t
1684bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
1685{
Maggie50444a32010-11-29 18:26:32 -08001686 u32 pgnum, loff;
1687 __be32 r32;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001688 int i, len;
1689 u32 *buf = tbuf;
1690
1691 pgnum = bfa_ioc_smem_pgnum(ioc, soff);
1692 loff = bfa_ioc_smem_pgoff(ioc, soff);
1693 bfa_trc(ioc, pgnum);
1694 bfa_trc(ioc, loff);
1695 bfa_trc(ioc, sz);
1696
1697 /*
1698 * Hold semaphore to serialize pll init and fwtrc.
1699 */
1700 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1701 bfa_trc(ioc, 0);
1702 return BFA_STATUS_FAILED;
1703 }
1704
Jing Huang53440262010-10-18 17:12:29 -07001705 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001706
1707 len = sz/sizeof(u32);
1708 bfa_trc(ioc, len);
1709 for (i = 0; i < len; i++) {
1710 r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huangba816ea2010-10-18 17:10:50 -07001711 buf[i] = be32_to_cpu(r32);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001712 loff += sizeof(u32);
1713
Jing Huang5fbe25c2010-10-18 17:17:23 -07001714 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001715 * handle page offset wrap around
1716 */
1717 loff = PSS_SMEM_PGOFF(loff);
1718 if (loff == 0) {
1719 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001720 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001721 }
1722 }
Jing Huang53440262010-10-18 17:12:29 -07001723 writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001724 /*
1725 * release semaphore.
1726 */
1727 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
1728
1729 bfa_trc(ioc, pgnum);
1730 return BFA_STATUS_OK;
1731}
1732
Jing Huang5fbe25c2010-10-18 17:17:23 -07001733/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001734 * Clear SMEM data from host through PCI memmap
1735 *
1736 * @param[in] ioc memory for IOC
1737 * @param[in] soff smem offset
1738 * @param[in] sz size of smem in bytes
1739 */
1740static bfa_status_t
1741bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
1742{
1743 int i, len;
1744 u32 pgnum, loff;
1745
1746 pgnum = bfa_ioc_smem_pgnum(ioc, soff);
1747 loff = bfa_ioc_smem_pgoff(ioc, soff);
1748 bfa_trc(ioc, pgnum);
1749 bfa_trc(ioc, loff);
1750 bfa_trc(ioc, sz);
1751
1752 /*
1753 * Hold semaphore to serialize pll init and fwtrc.
1754 */
1755 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1756 bfa_trc(ioc, 0);
1757 return BFA_STATUS_FAILED;
1758 }
1759
Jing Huang53440262010-10-18 17:12:29 -07001760 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001761
1762 len = sz/sizeof(u32); /* len in words */
1763 bfa_trc(ioc, len);
1764 for (i = 0; i < len; i++) {
1765 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
1766 loff += sizeof(u32);
1767
Jing Huang5fbe25c2010-10-18 17:17:23 -07001768 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001769 * handle page offset wrap around
1770 */
1771 loff = PSS_SMEM_PGOFF(loff);
1772 if (loff == 0) {
1773 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001774 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001775 }
1776 }
Jing Huang53440262010-10-18 17:12:29 -07001777 writel(bfa_ioc_smem_pgnum(ioc, 0), ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001778
1779 /*
1780 * release semaphore.
1781 */
1782 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
1783 bfa_trc(ioc, pgnum);
1784 return BFA_STATUS_OK;
1785}
1786
Jing Huang5fbe25c2010-10-18 17:17:23 -07001787/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001788 * hal iocpf to ioc interface
1789 */
1790static void
1791bfa_ioc_pf_enabled(struct bfa_ioc_s *ioc)
1792{
1793 bfa_fsm_send_event(ioc, IOC_E_ENABLED);
1794}
1795
1796static void
1797bfa_ioc_pf_disabled(struct bfa_ioc_s *ioc)
1798{
1799 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
1800}
1801
1802static void
1803bfa_ioc_pf_failed(struct bfa_ioc_s *ioc)
1804{
1805 bfa_fsm_send_event(ioc, IOC_E_FAILED);
1806}
1807
1808static void
1809bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
1810{
1811 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Jing Huang5fbe25c2010-10-18 17:17:23 -07001812 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001813 * Provide enable completion callback.
1814 */
1815 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Jing Huang88166242010-12-09 17:11:53 -08001816 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001817 "Running firmware version is incompatible "
1818 "with the driver version\n");
1819}
1820
1821
1822
Jing Huang5fbe25c2010-10-18 17:17:23 -07001823/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001824 * hal_ioc_public
1825 */
1826
1827bfa_status_t
1828bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1829{
1830
1831 /*
1832 * Hold semaphore so that nobody can access the chip during init.
1833 */
1834 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1835
1836 bfa_ioc_pll_init_asic(ioc);
1837
1838 ioc->pllinit = BFA_TRUE;
1839 /*
1840 * release semaphore.
1841 */
1842 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
1843
1844 return BFA_STATUS_OK;
1845}
Jing Huang7725ccf2009-09-23 17:46:15 -07001846
Jing Huang5fbe25c2010-10-18 17:17:23 -07001847/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001848 * Interface used by diag module to do firmware boot with memory test
1849 * as the entry vector.
1850 */
1851void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001852bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001853{
Jing Huang53440262010-10-18 17:12:29 -07001854 void __iomem *rb;
Jing Huang7725ccf2009-09-23 17:46:15 -07001855
1856 bfa_ioc_stats(ioc, ioc_boots);
1857
1858 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1859 return;
1860
Jing Huang5fbe25c2010-10-18 17:17:23 -07001861 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001862 * Initialize IOC state of all functions on a chip reset.
1863 */
1864 rb = ioc->pcidev.pci_bar_kva;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001865 if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
Jing Huang53440262010-10-18 17:12:29 -07001866 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
1867 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
Jing Huang7725ccf2009-09-23 17:46:15 -07001868 } else {
Jing Huang53440262010-10-18 17:12:29 -07001869 writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
1870 writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
Jing Huang7725ccf2009-09-23 17:46:15 -07001871 }
1872
Jing Huang07b28382010-07-08 19:59:24 -07001873 bfa_ioc_msgflush(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001874 bfa_ioc_download_fw(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001875
Jing Huang5fbe25c2010-10-18 17:17:23 -07001876 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001877 * Enable interrupts just before starting LPU
1878 */
1879 ioc->cbfn->reset_cbfn(ioc->bfa);
1880 bfa_ioc_lpu_start(ioc);
1881}
1882
Jing Huang5fbe25c2010-10-18 17:17:23 -07001883/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001884 * Enable/disable IOC failure auto recovery.
1885 */
1886void
1887bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
1888{
Krishna Gudipati2f9b8852010-03-03 17:42:51 -08001889 bfa_auto_recover = auto_recover;
Jing Huang7725ccf2009-09-23 17:46:15 -07001890}
1891
1892
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001893
Jing Huang7725ccf2009-09-23 17:46:15 -07001894bfa_boolean_t
1895bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
1896{
1897 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
1898}
1899
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001900bfa_boolean_t
1901bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
1902{
Jing Huang53440262010-10-18 17:12:29 -07001903 u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001904
1905 return ((r32 != BFI_IOC_UNINIT) &&
1906 (r32 != BFI_IOC_INITING) &&
1907 (r32 != BFI_IOC_MEMTEST));
1908}
1909
Jing Huang7725ccf2009-09-23 17:46:15 -07001910void
1911bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
1912{
Maggie50444a32010-11-29 18:26:32 -08001913 __be32 *msgp = mbmsg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001914 u32 r32;
1915 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001916
Jing Huang5fbe25c2010-10-18 17:17:23 -07001917 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001918 * read the MBOX msg
1919 */
1920 for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
1921 i++) {
Jing Huang53440262010-10-18 17:12:29 -07001922 r32 = readl(ioc->ioc_regs.lpu_mbox +
Jing Huang7725ccf2009-09-23 17:46:15 -07001923 i * sizeof(u32));
Jing Huangba816ea2010-10-18 17:10:50 -07001924 msgp[i] = cpu_to_be32(r32);
Jing Huang7725ccf2009-09-23 17:46:15 -07001925 }
1926
Jing Huang5fbe25c2010-10-18 17:17:23 -07001927 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001928 * turn off mailbox interrupt by clearing mailbox status
1929 */
Jing Huang53440262010-10-18 17:12:29 -07001930 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1931 readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001932}
1933
1934void
1935bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
1936{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001937 union bfi_ioc_i2h_msg_u *msg;
1938 struct bfa_iocpf_s *iocpf = &ioc->iocpf;
Jing Huang7725ccf2009-09-23 17:46:15 -07001939
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001940 msg = (union bfi_ioc_i2h_msg_u *) m;
Jing Huang7725ccf2009-09-23 17:46:15 -07001941
1942 bfa_ioc_stats(ioc, ioc_isrs);
1943
1944 switch (msg->mh.msg_id) {
1945 case BFI_IOC_I2H_HBEAT:
1946 break;
1947
1948 case BFI_IOC_I2H_READY_EVENT:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001949 bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001950 break;
1951
1952 case BFI_IOC_I2H_ENABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001953 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001954 break;
1955
1956 case BFI_IOC_I2H_DISABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001957 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001958 break;
1959
1960 case BFI_IOC_I2H_GETATTR_REPLY:
1961 bfa_ioc_getattr_reply(ioc);
1962 break;
1963
1964 default:
1965 bfa_trc(ioc, msg->mh.msg_id);
1966 bfa_assert(0);
1967 }
1968}
1969
Jing Huang5fbe25c2010-10-18 17:17:23 -07001970/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001971 * IOC attach time initialization and setup.
1972 *
1973 * @param[in] ioc memory for IOC
1974 * @param[in] bfa driver instance structure
Jing Huang7725ccf2009-09-23 17:46:15 -07001975 */
1976void
1977bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001978 struct bfa_timer_mod_s *timer_mod)
Jing Huang7725ccf2009-09-23 17:46:15 -07001979{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001980 ioc->bfa = bfa;
1981 ioc->cbfn = cbfn;
1982 ioc->timer_mod = timer_mod;
1983 ioc->fcmode = BFA_FALSE;
1984 ioc->pllinit = BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001985 ioc->dbg_fwsave_once = BFA_TRUE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001986 ioc->iocpf.ioc = ioc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001987
1988 bfa_ioc_mbox_attach(ioc);
1989 INIT_LIST_HEAD(&ioc->hb_notify_q);
1990
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001991 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
1992 bfa_fsm_send_event(ioc, IOC_E_RESET);
Jing Huang7725ccf2009-09-23 17:46:15 -07001993}
1994
Jing Huang5fbe25c2010-10-18 17:17:23 -07001995/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001996 * Driver detach time IOC cleanup.
1997 */
1998void
1999bfa_ioc_detach(struct bfa_ioc_s *ioc)
2000{
2001 bfa_fsm_send_event(ioc, IOC_E_DETACH);
2002}
2003
Jing Huang5fbe25c2010-10-18 17:17:23 -07002004/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002005 * Setup IOC PCI properties.
2006 *
2007 * @param[in] pcidev PCI device information for this IOC
2008 */
2009void
2010bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
2011 enum bfi_mclass mc)
2012{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002013 ioc->ioc_mc = mc;
2014 ioc->pcidev = *pcidev;
2015 ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
2016 ioc->cna = ioc->ctdev && !ioc->fcmode;
Jing Huang7725ccf2009-09-23 17:46:15 -07002017
Jing Huang5fbe25c2010-10-18 17:17:23 -07002018 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002019 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
2020 */
2021 if (ioc->ctdev)
2022 bfa_ioc_set_ct_hwif(ioc);
2023 else
2024 bfa_ioc_set_cb_hwif(ioc);
2025
Jing Huang7725ccf2009-09-23 17:46:15 -07002026 bfa_ioc_map_port(ioc);
2027 bfa_ioc_reg_init(ioc);
2028}
2029
Jing Huang5fbe25c2010-10-18 17:17:23 -07002030/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002031 * Initialize IOC dma memory
2032 *
2033 * @param[in] dm_kva kernel virtual address of IOC dma memory
2034 * @param[in] dm_pa physical address of IOC dma memory
2035 */
2036void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002037bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
Jing Huang7725ccf2009-09-23 17:46:15 -07002038{
Jing Huang5fbe25c2010-10-18 17:17:23 -07002039 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002040 * dma memory for firmware attribute
2041 */
2042 ioc->attr_dma.kva = dm_kva;
2043 ioc->attr_dma.pa = dm_pa;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002044 ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07002045}
2046
Jing Huang5fbe25c2010-10-18 17:17:23 -07002047/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002048 * Return size of dma memory required.
2049 */
2050u32
2051bfa_ioc_meminfo(void)
2052{
2053 return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ);
2054}
2055
2056void
2057bfa_ioc_enable(struct bfa_ioc_s *ioc)
2058{
2059 bfa_ioc_stats(ioc, ioc_enables);
2060 ioc->dbg_fwsave_once = BFA_TRUE;
2061
2062 bfa_fsm_send_event(ioc, IOC_E_ENABLE);
2063}
2064
2065void
2066bfa_ioc_disable(struct bfa_ioc_s *ioc)
2067{
2068 bfa_ioc_stats(ioc, ioc_disables);
2069 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
2070}
2071
Jing Huang5fbe25c2010-10-18 17:17:23 -07002072/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002073 * Returns memory required for saving firmware trace in case of crash.
2074 * Driver must call this interface to allocate memory required for
2075 * automatic saving of firmware trace. Driver should call
2076 * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this
2077 * trace memory.
2078 */
2079int
2080bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover)
2081{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002082 return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
Jing Huang7725ccf2009-09-23 17:46:15 -07002083}
2084
Jing Huang5fbe25c2010-10-18 17:17:23 -07002085/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002086 * Initialize memory for saving firmware trace. Driver must initialize
2087 * trace memory before call bfa_ioc_enable().
2088 */
2089void
2090bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
2091{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002092 ioc->dbg_fwsave = dbg_fwsave;
2093 ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->iocpf.auto_recover);
Jing Huang7725ccf2009-09-23 17:46:15 -07002094}
2095
2096u32
2097bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr)
2098{
2099 return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
2100}
2101
2102u32
2103bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr)
2104{
2105 return PSS_SMEM_PGOFF(fmaddr);
2106}
2107
Jing Huang5fbe25c2010-10-18 17:17:23 -07002108/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002109 * Register mailbox message handler functions
2110 *
2111 * @param[in] ioc IOC instance
2112 * @param[in] mcfuncs message class handler functions
2113 */
2114void
2115bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
2116{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002117 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2118 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002119
2120 for (mc = 0; mc < BFI_MC_MAX; mc++)
2121 mod->mbhdlr[mc].cbfn = mcfuncs[mc];
2122}
2123
Jing Huang5fbe25c2010-10-18 17:17:23 -07002124/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002125 * Register mailbox message handler function, to be called by common modules
2126 */
2127void
2128bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
2129 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2130{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002131 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
Jing Huang7725ccf2009-09-23 17:46:15 -07002132
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002133 mod->mbhdlr[mc].cbfn = cbfn;
2134 mod->mbhdlr[mc].cbarg = cbarg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002135}
2136
Jing Huang5fbe25c2010-10-18 17:17:23 -07002137/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002138 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2139 * Responsibility of caller to serialize
2140 *
2141 * @param[in] ioc IOC instance
2142 * @param[i] cmd Mailbox command
2143 */
2144void
2145bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
2146{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002147 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2148 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07002149
Jing Huang5fbe25c2010-10-18 17:17:23 -07002150 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002151 * If a previous command is pending, queue new command
2152 */
2153 if (!list_empty(&mod->cmd_q)) {
2154 list_add_tail(&cmd->qe, &mod->cmd_q);
2155 return;
2156 }
2157
Jing Huang5fbe25c2010-10-18 17:17:23 -07002158 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002159 * If mailbox is busy, queue command for poll timer
2160 */
Jing Huang53440262010-10-18 17:12:29 -07002161 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07002162 if (stat) {
2163 list_add_tail(&cmd->qe, &mod->cmd_q);
2164 return;
2165 }
2166
Jing Huang5fbe25c2010-10-18 17:17:23 -07002167 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002168 * mailbox is free -- queue command to firmware
2169 */
2170 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
2171}
2172
Jing Huang5fbe25c2010-10-18 17:17:23 -07002173/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002174 * Handle mailbox interrupts
2175 */
2176void
2177bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
2178{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002179 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2180 struct bfi_mbmsg_s m;
2181 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002182
2183 bfa_ioc_msgget(ioc, &m);
2184
Jing Huang5fbe25c2010-10-18 17:17:23 -07002185 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002186 * Treat IOC message class as special.
2187 */
2188 mc = m.mh.msg_class;
2189 if (mc == BFI_MC_IOC) {
2190 bfa_ioc_isr(ioc, &m);
2191 return;
2192 }
2193
2194 if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2195 return;
2196
2197 mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
2198}
2199
2200void
2201bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
2202{
2203 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2204}
2205
Jing Huanged969322010-07-08 19:45:56 -07002206void
2207bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
2208{
2209 ioc->fcmode = BFA_TRUE;
2210 ioc->port_id = bfa_ioc_pcifn(ioc);
2211}
2212
Jing Huang5fbe25c2010-10-18 17:17:23 -07002213/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002214 * return true if IOC is disabled
2215 */
2216bfa_boolean_t
2217bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
2218{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002219 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2220 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
Jing Huang7725ccf2009-09-23 17:46:15 -07002221}
2222
Jing Huang5fbe25c2010-10-18 17:17:23 -07002223/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002224 * return true if IOC firmware is different.
2225 */
2226bfa_boolean_t
2227bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2228{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002229 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
2230 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
2231 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
Jing Huang7725ccf2009-09-23 17:46:15 -07002232}
2233
2234#define bfa_ioc_state_disabled(__sm) \
2235 (((__sm) == BFI_IOC_UNINIT) || \
2236 ((__sm) == BFI_IOC_INITING) || \
2237 ((__sm) == BFI_IOC_HWINIT) || \
2238 ((__sm) == BFI_IOC_DISABLED) || \
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002239 ((__sm) == BFI_IOC_FAIL) || \
Jing Huang7725ccf2009-09-23 17:46:15 -07002240 ((__sm) == BFI_IOC_CFG_DISABLED))
2241
Jing Huang5fbe25c2010-10-18 17:17:23 -07002242/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002243 * Check if adapter is disabled -- both IOCs should be in a disabled
2244 * state.
2245 */
2246bfa_boolean_t
2247bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
2248{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002249 u32 ioc_state;
Jing Huang53440262010-10-18 17:12:29 -07002250 void __iomem *rb = ioc->pcidev.pci_bar_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07002251
2252 if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
2253 return BFA_FALSE;
2254
Jing Huang53440262010-10-18 17:12:29 -07002255 ioc_state = readl(rb + BFA_IOC0_STATE_REG);
Jing Huang7725ccf2009-09-23 17:46:15 -07002256 if (!bfa_ioc_state_disabled(ioc_state))
2257 return BFA_FALSE;
2258
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002259 if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
Jing Huang53440262010-10-18 17:12:29 -07002260 ioc_state = readl(rb + BFA_IOC1_STATE_REG);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002261 if (!bfa_ioc_state_disabled(ioc_state))
2262 return BFA_FALSE;
2263 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002264
2265 return BFA_TRUE;
2266}
2267
Jing Huang5fbe25c2010-10-18 17:17:23 -07002268/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002269 * Add to IOC heartbeat failure notification queue. To be used by common
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002270 * modules such as cee, port, diag.
Jing Huang7725ccf2009-09-23 17:46:15 -07002271 */
2272void
2273bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc,
2274 struct bfa_ioc_hbfail_notify_s *notify)
2275{
2276 list_add_tail(&notify->qe, &ioc->hb_notify_q);
2277}
2278
2279#define BFA_MFG_NAME "Brocade"
2280void
2281bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2282 struct bfa_adapter_attr_s *ad_attr)
2283{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002284 struct bfi_ioc_attr_s *ioc_attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002285
2286 ioc_attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002287
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002288 bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2289 bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2290 bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2291 bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
Jing Huang6a18b162010-10-18 17:08:54 -07002292 memcpy(&ad_attr->vpd, &ioc_attr->vpd,
Jing Huang7725ccf2009-09-23 17:46:15 -07002293 sizeof(struct bfa_mfg_vpd_s));
2294
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002295 ad_attr->nports = bfa_ioc_get_nports(ioc);
2296 ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002297
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002298 bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2299 /* For now, model descr uses same model string */
2300 bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
Jing Huang7725ccf2009-09-23 17:46:15 -07002301
Jing Huanged969322010-07-08 19:45:56 -07002302 ad_attr->card_type = ioc_attr->card_type;
2303 ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2304
Jing Huang7725ccf2009-09-23 17:46:15 -07002305 if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2306 ad_attr->prototype = 1;
2307 else
2308 ad_attr->prototype = 0;
2309
Jing Huang7725ccf2009-09-23 17:46:15 -07002310 ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002311 ad_attr->mac = bfa_ioc_get_mac(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002312
2313 ad_attr->pcie_gen = ioc_attr->pcie_gen;
2314 ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2315 ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2316 ad_attr->asic_rev = ioc_attr->asic_rev;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002317
2318 bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
Jing Huang7725ccf2009-09-23 17:46:15 -07002319
2320 ad_attr->cna_capable = ioc->cna;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002321 ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
Jing Huang7725ccf2009-09-23 17:46:15 -07002322}
2323
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002324enum bfa_ioc_type_e
2325bfa_ioc_get_type(struct bfa_ioc_s *ioc)
2326{
2327 if (!ioc->ctdev || ioc->fcmode)
2328 return BFA_IOC_TYPE_FC;
2329 else if (ioc->ioc_mc == BFI_MC_IOCFC)
2330 return BFA_IOC_TYPE_FCoE;
2331 else if (ioc->ioc_mc == BFI_MC_LL)
2332 return BFA_IOC_TYPE_LL;
2333 else {
2334 bfa_assert(ioc->ioc_mc == BFI_MC_LL);
2335 return BFA_IOC_TYPE_LL;
2336 }
2337}
2338
Jing Huang7725ccf2009-09-23 17:46:15 -07002339void
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002340bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)
2341{
Jing Huang6a18b162010-10-18 17:08:54 -07002342 memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2343 memcpy((void *)serial_num,
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002344 (void *)ioc->attr->brcd_serialnum,
2345 BFA_ADAPTER_SERIAL_NUM_LEN);
2346}
2347
2348void
2349bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
2350{
Jing Huang6a18b162010-10-18 17:08:54 -07002351 memset((void *)fw_ver, 0, BFA_VERSION_LEN);
2352 memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002353}
2354
2355void
2356bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
2357{
2358 bfa_assert(chip_rev);
2359
Jing Huang6a18b162010-10-18 17:08:54 -07002360 memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002361
2362 chip_rev[0] = 'R';
2363 chip_rev[1] = 'e';
2364 chip_rev[2] = 'v';
2365 chip_rev[3] = '-';
2366 chip_rev[4] = ioc->attr->asic_rev;
2367 chip_rev[5] = '\0';
2368}
2369
2370void
2371bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
2372{
Jing Huang6a18b162010-10-18 17:08:54 -07002373 memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
2374 memcpy(optrom_ver, ioc->attr->optrom_version,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002375 BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002376}
2377
2378void
2379bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
2380{
Jing Huang6a18b162010-10-18 17:08:54 -07002381 memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2382 memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002383}
2384
2385void
2386bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
2387{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002388 struct bfi_ioc_attr_s *ioc_attr;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002389
2390 bfa_assert(model);
Jing Huang6a18b162010-10-18 17:08:54 -07002391 memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002392
2393 ioc_attr = ioc->attr;
2394
Jing Huang5fbe25c2010-10-18 17:17:23 -07002395 /*
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002396 * model name
2397 */
Jing Huang6a18b162010-10-18 17:08:54 -07002398 snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002399 BFA_MFG_NAME, ioc_attr->card_type);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002400}
2401
2402enum bfa_ioc_state
2403bfa_ioc_get_state(struct bfa_ioc_s *ioc)
2404{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002405 enum bfa_iocpf_state iocpf_st;
2406 enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2407
2408 if (ioc_st == BFA_IOC_ENABLING ||
2409 ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2410
2411 iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2412
2413 switch (iocpf_st) {
2414 case BFA_IOCPF_SEMWAIT:
2415 ioc_st = BFA_IOC_SEMWAIT;
2416 break;
2417
2418 case BFA_IOCPF_HWINIT:
2419 ioc_st = BFA_IOC_HWINIT;
2420 break;
2421
2422 case BFA_IOCPF_FWMISMATCH:
2423 ioc_st = BFA_IOC_FWMISMATCH;
2424 break;
2425
2426 case BFA_IOCPF_FAIL:
2427 ioc_st = BFA_IOC_FAIL;
2428 break;
2429
2430 case BFA_IOCPF_INITFAIL:
2431 ioc_st = BFA_IOC_INITFAIL;
2432 break;
2433
2434 default:
2435 break;
2436 }
2437 }
2438
2439 return ioc_st;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002440}
2441
2442void
Jing Huang7725ccf2009-09-23 17:46:15 -07002443bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2444{
Jing Huang6a18b162010-10-18 17:08:54 -07002445 memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
Jing Huang7725ccf2009-09-23 17:46:15 -07002446
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002447 ioc_attr->state = bfa_ioc_get_state(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002448 ioc_attr->port_id = ioc->port_id;
2449
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002450 ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002451
2452 bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2453
2454 ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2455 ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002456 bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
Jing Huang7725ccf2009-09-23 17:46:15 -07002457}
2458
Jing Huang5fbe25c2010-10-18 17:17:23 -07002459/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002460 * hal_wwn_public
Jing Huang7725ccf2009-09-23 17:46:15 -07002461 */
2462wwn_t
2463bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc)
2464{
Jing Huang15b64a82010-07-08 19:48:12 -07002465 return ioc->attr->pwwn;
Jing Huang7725ccf2009-09-23 17:46:15 -07002466}
2467
2468wwn_t
2469bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc)
2470{
Jing Huang15b64a82010-07-08 19:48:12 -07002471 return ioc->attr->nwwn;
Jing Huang7725ccf2009-09-23 17:46:15 -07002472}
2473
Jing Huang7725ccf2009-09-23 17:46:15 -07002474u64
2475bfa_ioc_get_adid(struct bfa_ioc_s *ioc)
2476{
Jing Huang15b64a82010-07-08 19:48:12 -07002477 return ioc->attr->mfg_pwwn;
Jing Huang7725ccf2009-09-23 17:46:15 -07002478}
2479
2480mac_t
2481bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2482{
Jing Huang15b64a82010-07-08 19:48:12 -07002483 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002484 * Check the IOC type and return the appropriate MAC
Jing Huang15b64a82010-07-08 19:48:12 -07002485 */
2486 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002487 return ioc->attr->fcoe_mac;
Jing Huang15b64a82010-07-08 19:48:12 -07002488 else
2489 return ioc->attr->mac;
2490}
2491
2492wwn_t
2493bfa_ioc_get_mfg_pwwn(struct bfa_ioc_s *ioc)
2494{
2495 return ioc->attr->mfg_pwwn;
2496}
2497
2498wwn_t
2499bfa_ioc_get_mfg_nwwn(struct bfa_ioc_s *ioc)
2500{
2501 return ioc->attr->mfg_nwwn;
2502}
2503
2504mac_t
2505bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
2506{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002507 mac_t m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002508
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002509 m = ioc->attr->mfg_mac;
2510 if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
2511 m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2512 else
2513 bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
2514 bfa_ioc_pcifn(ioc));
Jing Huang7725ccf2009-09-23 17:46:15 -07002515
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002516 return m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002517}
2518
Jing Huang7725ccf2009-09-23 17:46:15 -07002519bfa_boolean_t
2520bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
2521{
Jing Huang293f82d2010-07-08 19:45:20 -07002522 return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id);
Jing Huang7725ccf2009-09-23 17:46:15 -07002523}
2524
Jing Huang5fbe25c2010-10-18 17:17:23 -07002525/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002526 * Retrieve saved firmware trace from a prior IOC failure.
2527 */
2528bfa_status_t
2529bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2530{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002531 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002532
2533 if (ioc->dbg_fwsave_len == 0)
2534 return BFA_STATUS_ENOFSAVE;
2535
2536 tlen = *trclen;
2537 if (tlen > ioc->dbg_fwsave_len)
2538 tlen = ioc->dbg_fwsave_len;
2539
Jing Huang6a18b162010-10-18 17:08:54 -07002540 memcpy(trcdata, ioc->dbg_fwsave, tlen);
Jing Huang7725ccf2009-09-23 17:46:15 -07002541 *trclen = tlen;
2542 return BFA_STATUS_OK;
2543}
2544
Jing Huang5fbe25c2010-10-18 17:17:23 -07002545/*
Krishna Gudipati738c9e62010-03-05 19:36:19 -08002546 * Clear saved firmware trace
2547 */
2548void
2549bfa_ioc_debug_fwsave_clear(struct bfa_ioc_s *ioc)
2550{
2551 ioc->dbg_fwsave_once = BFA_TRUE;
2552}
2553
Jing Huang5fbe25c2010-10-18 17:17:23 -07002554/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002555 * Retrieve saved firmware trace from a prior IOC failure.
2556 */
2557bfa_status_t
2558bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2559{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002560 u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2561 int tlen;
2562 bfa_status_t status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002563
2564 bfa_trc(ioc, *trclen);
2565
Jing Huang7725ccf2009-09-23 17:46:15 -07002566 tlen = *trclen;
2567 if (tlen > BFA_DBG_FWTRC_LEN)
2568 tlen = BFA_DBG_FWTRC_LEN;
Jing Huang7725ccf2009-09-23 17:46:15 -07002569
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002570 status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
2571 *trclen = tlen;
2572 return status;
2573}
Jing Huang7725ccf2009-09-23 17:46:15 -07002574
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002575static void
2576bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
2577{
2578 struct bfa_mbox_cmd_s cmd;
2579 struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002580
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002581 bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
2582 bfa_ioc_portid(ioc));
2583 req->ioc_class = ioc->ioc_mc;
2584 bfa_ioc_mbox_queue(ioc, &cmd);
2585}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002586
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002587static void
2588bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
2589{
2590 u32 fwsync_iter = 1000;
2591
2592 bfa_ioc_send_fwsync(ioc);
2593
Jing Huang5fbe25c2010-10-18 17:17:23 -07002594 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002595 * After sending a fw sync mbox command wait for it to
2596 * take effect. We will not wait for a response because
2597 * 1. fw_sync mbox cmd doesn't have a response.
2598 * 2. Even if we implement that, interrupts might not
2599 * be enabled when we call this function.
2600 * So, just keep checking if any mbox cmd is pending, and
2601 * after waiting for a reasonable amount of time, go ahead.
2602 * It is possible that fw has crashed and the mbox command
2603 * is never acknowledged.
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002604 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002605 while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
2606 fwsync_iter--;
2607}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002608
Jing Huang5fbe25c2010-10-18 17:17:23 -07002609/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002610 * Dump firmware smem
2611 */
2612bfa_status_t
2613bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
2614 u32 *offset, int *buflen)
2615{
2616 u32 loff;
2617 int dlen;
2618 bfa_status_t status;
2619 u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002620
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002621 if (*offset >= smem_len) {
2622 *offset = *buflen = 0;
2623 return BFA_STATUS_EINVAL;
2624 }
2625
2626 loff = *offset;
2627 dlen = *buflen;
2628
Jing Huang5fbe25c2010-10-18 17:17:23 -07002629 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002630 * First smem read, sync smem before proceeding
2631 * No need to sync before reading every chunk.
2632 */
2633 if (loff == 0)
2634 bfa_ioc_fwsync(ioc);
2635
2636 if ((loff + dlen) >= smem_len)
2637 dlen = smem_len - loff;
2638
2639 status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
2640
2641 if (status != BFA_STATUS_OK) {
2642 *offset = *buflen = 0;
2643 return status;
2644 }
2645
2646 *offset += dlen;
2647
2648 if (*offset >= smem_len)
2649 *offset = 0;
2650
2651 *buflen = dlen;
2652
2653 return status;
2654}
2655
Jing Huang5fbe25c2010-10-18 17:17:23 -07002656/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002657 * Firmware statistics
2658 */
2659bfa_status_t
2660bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
2661{
2662 u32 loff = BFI_IOC_FWSTATS_OFF + \
2663 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2664 int tlen;
2665 bfa_status_t status;
2666
2667 if (ioc->stats_busy) {
2668 bfa_trc(ioc, ioc->stats_busy);
2669 return BFA_STATUS_DEVBUSY;
2670 }
2671 ioc->stats_busy = BFA_TRUE;
2672
2673 tlen = sizeof(struct bfa_fw_stats_s);
2674 status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
2675
2676 ioc->stats_busy = BFA_FALSE;
2677 return status;
2678}
2679
2680bfa_status_t
2681bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2682{
2683 u32 loff = BFI_IOC_FWSTATS_OFF + \
2684 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2685 int tlen;
2686 bfa_status_t status;
2687
2688 if (ioc->stats_busy) {
2689 bfa_trc(ioc, ioc->stats_busy);
2690 return BFA_STATUS_DEVBUSY;
2691 }
2692 ioc->stats_busy = BFA_TRUE;
2693
2694 tlen = sizeof(struct bfa_fw_stats_s);
2695 status = bfa_ioc_smem_clr(ioc, loff, tlen);
2696
2697 ioc->stats_busy = BFA_FALSE;
2698 return status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002699}
2700
Jing Huang5fbe25c2010-10-18 17:17:23 -07002701/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002702 * Save firmware trace if configured.
2703 */
2704static void
2705bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
2706{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002707 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002708
2709 if (ioc->dbg_fwsave_len) {
2710 tlen = ioc->dbg_fwsave_len;
2711 bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2712 }
2713}
2714
Jing Huang5fbe25c2010-10-18 17:17:23 -07002715/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002716 * Firmware failure detected. Start recovery actions.
2717 */
2718static void
2719bfa_ioc_recover(struct bfa_ioc_s *ioc)
2720{
2721 if (ioc->dbg_fwsave_once) {
2722 ioc->dbg_fwsave_once = BFA_FALSE;
2723 bfa_ioc_debug_save(ioc);
2724 }
2725
2726 bfa_ioc_stats(ioc, ioc_hbfails);
2727 bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2728}
2729
Jing Huang7725ccf2009-09-23 17:46:15 -07002730static void
Jing Huang07b28382010-07-08 19:59:24 -07002731bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -07002732{
Jing Huang07b28382010-07-08 19:59:24 -07002733 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
2734 return;
Jing Huang7725ccf2009-09-23 17:46:15 -07002735}
2736
Jing Huang5fbe25c2010-10-18 17:17:23 -07002737/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002738 * hal_iocpf_pvt BFA IOC PF private functions
2739 */
2740
2741static void
2742bfa_iocpf_enable(struct bfa_ioc_s *ioc)
2743{
2744 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
2745}
2746
2747static void
2748bfa_iocpf_disable(struct bfa_ioc_s *ioc)
2749{
2750 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
2751}
2752
2753static void
2754bfa_iocpf_fail(struct bfa_ioc_s *ioc)
2755{
2756 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
2757}
2758
2759static void
2760bfa_iocpf_initfail(struct bfa_ioc_s *ioc)
2761{
2762 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
2763}
2764
2765static void
2766bfa_iocpf_getattrfail(struct bfa_ioc_s *ioc)
2767{
2768 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
2769}
2770
2771static void
2772bfa_iocpf_stop(struct bfa_ioc_s *ioc)
2773{
2774 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
2775}
2776
2777static void
2778bfa_iocpf_timeout(void *ioc_arg)
2779{
2780 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2781
2782 bfa_trc(ioc, 0);
2783 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
2784}
2785
2786static void
2787bfa_iocpf_sem_timeout(void *ioc_arg)
2788{
2789 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2790
2791 bfa_ioc_hw_sem_get(ioc);
2792}
2793
Jing Huang5fbe25c2010-10-18 17:17:23 -07002794/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002795 * bfa timer function
2796 */
2797void
2798bfa_timer_init(struct bfa_timer_mod_s *mod)
2799{
2800 INIT_LIST_HEAD(&mod->timer_q);
2801}
2802
2803void
2804bfa_timer_beat(struct bfa_timer_mod_s *mod)
2805{
2806 struct list_head *qh = &mod->timer_q;
2807 struct list_head *qe, *qe_next;
2808 struct bfa_timer_s *elem;
2809 struct list_head timedout_q;
2810
2811 INIT_LIST_HEAD(&timedout_q);
2812
2813 qe = bfa_q_next(qh);
2814
2815 while (qe != qh) {
2816 qe_next = bfa_q_next(qe);
2817
2818 elem = (struct bfa_timer_s *) qe;
2819 if (elem->timeout <= BFA_TIMER_FREQ) {
2820 elem->timeout = 0;
2821 list_del(&elem->qe);
2822 list_add_tail(&elem->qe, &timedout_q);
2823 } else {
2824 elem->timeout -= BFA_TIMER_FREQ;
2825 }
2826
2827 qe = qe_next; /* go to next elem */
2828 }
2829
2830 /*
2831 * Pop all the timeout entries
2832 */
2833 while (!list_empty(&timedout_q)) {
2834 bfa_q_deq(&timedout_q, &elem);
2835 elem->timercb(elem->arg);
2836 }
2837}
2838
Jing Huang5fbe25c2010-10-18 17:17:23 -07002839/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002840 * Should be called with lock protection
2841 */
2842void
2843bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
2844 void (*timercb) (void *), void *arg, unsigned int timeout)
2845{
2846
2847 bfa_assert(timercb != NULL);
2848 bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer));
2849
2850 timer->timeout = timeout;
2851 timer->timercb = timercb;
2852 timer->arg = arg;
2853
2854 list_add_tail(&timer->qe, &mod->timer_q);
2855}
2856
Jing Huang5fbe25c2010-10-18 17:17:23 -07002857/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002858 * Should be called with lock protection
2859 */
2860void
2861bfa_timer_stop(struct bfa_timer_s *timer)
2862{
2863 bfa_assert(!list_empty(&timer->qe));
2864
2865 list_del(&timer->qe);
2866}