blob: 9c6e493cb9c77321d5da4f289c64468cf8b6741b [file] [log] [blame]
Jing Huang7725ccf2009-09-23 17:46:15 -07001/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
Jing Huang7725ccf2009-09-23 17:46:15 -07003 * All rights reserved
4 * www.brocade.com
5 *
6 * Linux driver for Brocade Fibre Channel Host Bus Adapter.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License (GPL) Version 2 as
10 * published by the Free Software Foundation
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 */
17
Maggie Zhangf16a1752010-12-09 19:12:32 -080018#include "bfad_drv.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070019#include "bfa_ioc.h"
Krishna Gudipati11189202011-06-13 15:50:35 -070020#include "bfi_reg.h"
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070021#include "bfa_defs.h"
22#include "bfa_defs_svc.h"
Jing Huang7725ccf2009-09-23 17:46:15 -070023
Krishna Gudipati7af074d2010-03-05 19:35:45 -080024BFA_TRC_FILE(CNA, IOC);
Jing Huang7725ccf2009-09-23 17:46:15 -070025
Jing Huang5fbe25c2010-10-18 17:17:23 -070026/*
Jing Huang7725ccf2009-09-23 17:46:15 -070027 * IOC local definitions
28 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070029#define BFA_IOC_TOV 3000 /* msecs */
30#define BFA_IOC_HWSEM_TOV 500 /* msecs */
31#define BFA_IOC_HB_TOV 500 /* msecs */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070032#define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV
Krishna Gudipati775c7742011-06-13 15:52:12 -070033#define BFA_IOC_POLL_TOV BFA_TIMER_FREQ
Jing Huang7725ccf2009-09-23 17:46:15 -070034
35#define bfa_ioc_timer_start(__ioc) \
36 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
37 bfa_ioc_timeout, (__ioc), BFA_IOC_TOV)
38#define bfa_ioc_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
39
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070040#define bfa_hb_timer_start(__ioc) \
41 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->hb_timer, \
42 bfa_ioc_hb_check, (__ioc), BFA_IOC_HB_TOV)
43#define bfa_hb_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->hb_timer)
44
Jing Huang7725ccf2009-09-23 17:46:15 -070045#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
Jing Huang7725ccf2009-09-23 17:46:15 -070046
Jing Huang5fbe25c2010-10-18 17:17:23 -070047/*
Krishna Gudipati0a20de42010-03-05 19:34:20 -080048 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
49 */
50
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070051#define bfa_ioc_firmware_lock(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080052 ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070053#define bfa_ioc_firmware_unlock(__ioc) \
Krishna Gudipati0a20de42010-03-05 19:34:20 -080054 ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
Krishna Gudipati0a20de42010-03-05 19:34:20 -080055#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
56#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
Krishna Gudipatif1d584d2010-12-13 16:17:11 -080057#define bfa_ioc_notify_fail(__ioc) \
58 ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
Jing Huang45d7f0c2011-04-13 11:45:53 -070059#define bfa_ioc_sync_start(__ioc) \
60 ((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
Krishna Gudipatif1d584d2010-12-13 16:17:11 -080061#define bfa_ioc_sync_join(__ioc) \
62 ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
63#define bfa_ioc_sync_leave(__ioc) \
64 ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
65#define bfa_ioc_sync_ack(__ioc) \
66 ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
67#define bfa_ioc_sync_complete(__ioc) \
68 ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070069
70#define bfa_ioc_mbox_cmd_pending(__ioc) \
71 (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
Jing Huang53440262010-10-18 17:12:29 -070072 readl((__ioc)->ioc_regs.hfn_mbox_cmd))
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070073
74bfa_boolean_t bfa_auto_recover = BFA_TRUE;
Jing Huang7725ccf2009-09-23 17:46:15 -070075
76/*
77 * forward declarations
78 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070079static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070080static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force);
81static void bfa_ioc_timeout(void *ioc);
Krishna Gudipati775c7742011-06-13 15:52:12 -070082static void bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070083static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc);
84static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc);
85static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc);
86static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070087static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc);
88static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc);
89static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
90static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
Krishna Gudipatid37779f2011-06-13 15:42:10 -070091static void bfa_ioc_event_notify(struct bfa_ioc_s *ioc ,
92 enum bfa_ioc_event_e event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070093static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
94static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -080095static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
96static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -070097static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -070098
Jing Huang7725ccf2009-09-23 17:46:15 -070099
Jing Huang5fbe25c2010-10-18 17:17:23 -0700100/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700101 * IOC state machine definitions/declarations
Jing Huang7725ccf2009-09-23 17:46:15 -0700102 */
103enum ioc_event {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700104 IOC_E_RESET = 1, /* IOC reset request */
105 IOC_E_ENABLE = 2, /* IOC enable request */
106 IOC_E_DISABLE = 3, /* IOC disable request */
107 IOC_E_DETACH = 4, /* driver detach cleanup */
108 IOC_E_ENABLED = 5, /* f/w enabled */
109 IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
110 IOC_E_DISABLED = 7, /* f/w disabled */
Krishna Gudipati775c7742011-06-13 15:52:12 -0700111 IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */
112 IOC_E_HBFAIL = 9, /* heartbeat failure */
113 IOC_E_HWERROR = 10, /* hardware error interrupt */
114 IOC_E_TIMEOUT = 11, /* timeout */
Jing Huang7725ccf2009-09-23 17:46:15 -0700115};
116
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700117bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700118bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700119bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
120bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
121bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800122bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700123bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
Jing Huang7725ccf2009-09-23 17:46:15 -0700124bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
125bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
126
127static struct bfa_sm_table_s ioc_sm_table[] = {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700128 {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
Jing Huang7725ccf2009-09-23 17:46:15 -0700129 {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700130 {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
Jing Huang7725ccf2009-09-23 17:46:15 -0700131 {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
132 {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800133 {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700134 {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
Jing Huang7725ccf2009-09-23 17:46:15 -0700135 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
136 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
137};
138
Jing Huang5fbe25c2010-10-18 17:17:23 -0700139/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700140 * IOCPF state machine definitions/declarations
141 */
142
143#define bfa_iocpf_timer_start(__ioc) \
144 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
145 bfa_iocpf_timeout, (__ioc), BFA_IOC_TOV)
146#define bfa_iocpf_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer)
147
Krishna Gudipati775c7742011-06-13 15:52:12 -0700148#define bfa_iocpf_poll_timer_start(__ioc) \
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700149 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \
Krishna Gudipati775c7742011-06-13 15:52:12 -0700150 bfa_iocpf_poll_timeout, (__ioc), BFA_IOC_POLL_TOV)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700151
152#define bfa_sem_timer_start(__ioc) \
153 bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->sem_timer, \
154 bfa_iocpf_sem_timeout, (__ioc), BFA_IOC_HWSEM_TOV)
155#define bfa_sem_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->sem_timer)
156
157/*
158 * Forward declareations for iocpf state machine
159 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700160static void bfa_iocpf_timeout(void *ioc_arg);
161static void bfa_iocpf_sem_timeout(void *ioc_arg);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700162static void bfa_iocpf_poll_timeout(void *ioc_arg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700163
Jing Huang5fbe25c2010-10-18 17:17:23 -0700164/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700165 * IOCPF state machine events
166 */
167enum iocpf_event {
168 IOCPF_E_ENABLE = 1, /* IOCPF enable request */
169 IOCPF_E_DISABLE = 2, /* IOCPF disable request */
170 IOCPF_E_STOP = 3, /* stop on driver detach */
171 IOCPF_E_FWREADY = 4, /* f/w initialization done */
172 IOCPF_E_FWRSP_ENABLE = 5, /* enable f/w response */
173 IOCPF_E_FWRSP_DISABLE = 6, /* disable f/w response */
174 IOCPF_E_FAIL = 7, /* failure notice by ioc sm */
175 IOCPF_E_INITFAIL = 8, /* init fail notice by ioc sm */
176 IOCPF_E_GETATTRFAIL = 9, /* init fail notice by ioc sm */
177 IOCPF_E_SEMLOCKED = 10, /* h/w semaphore is locked */
178 IOCPF_E_TIMEOUT = 11, /* f/w response timeout */
179};
180
Jing Huang5fbe25c2010-10-18 17:17:23 -0700181/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700182 * IOCPF states
183 */
184enum bfa_iocpf_state {
185 BFA_IOCPF_RESET = 1, /* IOC is in reset state */
186 BFA_IOCPF_SEMWAIT = 2, /* Waiting for IOC h/w semaphore */
187 BFA_IOCPF_HWINIT = 3, /* IOC h/w is being initialized */
188 BFA_IOCPF_READY = 4, /* IOCPF is initialized */
189 BFA_IOCPF_INITFAIL = 5, /* IOCPF failed */
190 BFA_IOCPF_FAIL = 6, /* IOCPF failed */
191 BFA_IOCPF_DISABLING = 7, /* IOCPF is being disabled */
192 BFA_IOCPF_DISABLED = 8, /* IOCPF is disabled */
193 BFA_IOCPF_FWMISMATCH = 9, /* IOC f/w different from drivers */
194};
195
196bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf_s, enum iocpf_event);
197bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf_s, enum iocpf_event);
198bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf_s, enum iocpf_event);
199bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event);
200bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event);
201bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event);
202bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800203bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s,
204 enum iocpf_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700205bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800206bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700207bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event);
208bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800209bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s,
210 enum iocpf_event);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700211bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event);
212
213static struct bfa_sm_table_s iocpf_sm_table[] = {
214 {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
215 {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
216 {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
217 {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
218 {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
219 {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
220 {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800221 {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700222 {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800223 {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700224 {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
225 {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800226 {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700227 {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
228};
229
Jing Huang5fbe25c2010-10-18 17:17:23 -0700230/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700231 * IOC State Machine
232 */
233
Jing Huang5fbe25c2010-10-18 17:17:23 -0700234/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700235 * Beginning state. IOC uninit state.
236 */
237
238static void
239bfa_ioc_sm_uninit_entry(struct bfa_ioc_s *ioc)
240{
241}
242
Jing Huang5fbe25c2010-10-18 17:17:23 -0700243/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700244 * IOC is in uninit state.
245 */
246static void
247bfa_ioc_sm_uninit(struct bfa_ioc_s *ioc, enum ioc_event event)
248{
249 bfa_trc(ioc, event);
250
251 switch (event) {
252 case IOC_E_RESET:
253 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
254 break;
255
256 default:
257 bfa_sm_fault(ioc, event);
258 }
259}
Jing Huang5fbe25c2010-10-18 17:17:23 -0700260/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700261 * Reset entry actions -- initialize state machine
262 */
263static void
264bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc)
265{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700266 bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
Jing Huang7725ccf2009-09-23 17:46:15 -0700267}
268
Jing Huang5fbe25c2010-10-18 17:17:23 -0700269/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700270 * IOC is in reset state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700271 */
272static void
273bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event)
274{
275 bfa_trc(ioc, event);
276
277 switch (event) {
278 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700279 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
280 break;
281
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700282 case IOC_E_DISABLE:
283 bfa_ioc_disable_comp(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700284 break;
285
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700286 case IOC_E_DETACH:
287 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Jing Huang7725ccf2009-09-23 17:46:15 -0700288 break;
289
290 default:
291 bfa_sm_fault(ioc, event);
292 }
293}
294
295
296static void
297bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc)
298{
Maggie Zhangf7f73812010-12-09 19:08:43 -0800299 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -0700300}
301
Jing Huang5fbe25c2010-10-18 17:17:23 -0700302/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700303 * Host IOC function is being enabled, awaiting response from firmware.
304 * Semaphore is acquired.
305 */
306static void
307bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
308{
309 bfa_trc(ioc, event);
310
311 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700312 case IOC_E_ENABLED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700313 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
314 break;
315
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800316 case IOC_E_PFFAILED:
317 /* !!! fall through !!! */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700318 case IOC_E_HWERROR:
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800319 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700320 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800321 if (event != IOC_E_PFFAILED)
322 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700323 break;
324
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700325 case IOC_E_DISABLE:
326 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
327 break;
328
329 case IOC_E_DETACH:
330 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800331 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700332 break;
333
334 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700335 break;
336
337 default:
338 bfa_sm_fault(ioc, event);
339 }
340}
341
342
343static void
344bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc)
345{
346 bfa_ioc_timer_start(ioc);
347 bfa_ioc_send_getattr(ioc);
348}
349
Jing Huang5fbe25c2010-10-18 17:17:23 -0700350/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700351 * IOC configuration in progress. Timer is active.
352 */
353static void
354bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
355{
356 bfa_trc(ioc, event);
357
358 switch (event) {
359 case IOC_E_FWRSP_GETATTR:
360 bfa_ioc_timer_stop(ioc);
Jing Huang07b28382010-07-08 19:59:24 -0700361 bfa_ioc_check_attr_wwns(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700362 bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
363 break;
364
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700365 break;
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800366 case IOC_E_PFFAILED:
Jing Huang7725ccf2009-09-23 17:46:15 -0700367 case IOC_E_HWERROR:
368 bfa_ioc_timer_stop(ioc);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800369 /* !!! fall through !!! */
Jing Huang7725ccf2009-09-23 17:46:15 -0700370 case IOC_E_TIMEOUT:
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800371 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700372 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800373 if (event != IOC_E_PFFAILED)
374 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700375 break;
376
377 case IOC_E_DISABLE:
378 bfa_ioc_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700379 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
380 break;
381
382 case IOC_E_ENABLE:
Jing Huang7725ccf2009-09-23 17:46:15 -0700383 break;
384
385 default:
386 bfa_sm_fault(ioc, event);
387 }
388}
389
390
391static void
392bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
393{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700394 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
395
Jing Huang7725ccf2009-09-23 17:46:15 -0700396 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
Krishna Gudipatid37779f2011-06-13 15:42:10 -0700397 bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
Jing Huang7725ccf2009-09-23 17:46:15 -0700398 bfa_ioc_hb_monitor(ioc);
Jing Huang88166242010-12-09 17:11:53 -0800399 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700400}
401
402static void
403bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
404{
405 bfa_trc(ioc, event);
406
407 switch (event) {
408 case IOC_E_ENABLE:
409 break;
410
411 case IOC_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800412 bfa_hb_timer_stop(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -0700413 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
414 break;
415
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800416 case IOC_E_PFFAILED:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700417 case IOC_E_HWERROR:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800418 bfa_hb_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700419 /* !!! fall through !!! */
Jing Huang7725ccf2009-09-23 17:46:15 -0700420 case IOC_E_HBFAIL:
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800421 if (ioc->iocpf.auto_recover)
422 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
423 else
424 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
425
Krishna Gudipati775c7742011-06-13 15:52:12 -0700426 bfa_ioc_fail_notify(ioc);
427
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800428 if (event != IOC_E_PFFAILED)
429 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700430 break;
431
432 default:
433 bfa_sm_fault(ioc, event);
434 }
435}
436
437
438static void
439bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
440{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700441 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800442 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
Jing Huang88166242010-12-09 17:11:53 -0800443 BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
Jing Huang7725ccf2009-09-23 17:46:15 -0700444}
445
Jing Huang5fbe25c2010-10-18 17:17:23 -0700446/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700447 * IOC is being disabled
448 */
449static void
450bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event)
451{
452 bfa_trc(ioc, event);
453
454 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700455 case IOC_E_DISABLED:
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800456 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
457 break;
458
459 case IOC_E_HWERROR:
Jing Huang7725ccf2009-09-23 17:46:15 -0700460 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700461 * No state change. Will move to disabled state
462 * after iocpf sm completes failure processing and
463 * moves to disabled state.
Jing Huang7725ccf2009-09-23 17:46:15 -0700464 */
Maggie Zhangf7f73812010-12-09 19:08:43 -0800465 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
Jing Huang7725ccf2009-09-23 17:46:15 -0700466 break;
467
468 default:
469 bfa_sm_fault(ioc, event);
470 }
471}
472
Jing Huang5fbe25c2010-10-18 17:17:23 -0700473/*
Jing Huang7725ccf2009-09-23 17:46:15 -0700474 * IOC disable completion entry.
475 */
476static void
477bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc)
478{
479 bfa_ioc_disable_comp(ioc);
480}
481
482static void
483bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
484{
485 bfa_trc(ioc, event);
486
487 switch (event) {
488 case IOC_E_ENABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700489 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700490 break;
491
492 case IOC_E_DISABLE:
493 ioc->cbfn->disable_cbfn(ioc->bfa);
494 break;
495
Jing Huang7725ccf2009-09-23 17:46:15 -0700496 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700497 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800498 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700499 break;
500
501 default:
502 bfa_sm_fault(ioc, event);
503 }
504}
505
506
507static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800508bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -0700509{
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800510 bfa_trc(ioc, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700511}
512
Jing Huang5fbe25c2010-10-18 17:17:23 -0700513/*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800514 * Hardware initialization retry.
Jing Huang7725ccf2009-09-23 17:46:15 -0700515 */
516static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800517bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700518{
519 bfa_trc(ioc, event);
520
521 switch (event) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700522 case IOC_E_ENABLED:
523 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
524 break;
525
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800526 case IOC_E_PFFAILED:
527 case IOC_E_HWERROR:
Jing Huang5fbe25c2010-10-18 17:17:23 -0700528 /*
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800529 * Initialization retry failed.
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700530 */
531 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700532 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800533 if (event != IOC_E_PFFAILED)
534 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
535 break;
536
537 case IOC_E_ENABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700538 break;
539
Jing Huang7725ccf2009-09-23 17:46:15 -0700540 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700541 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700542 break;
543
544 case IOC_E_DETACH:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700545 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800546 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
Jing Huang7725ccf2009-09-23 17:46:15 -0700547 break;
548
549 default:
550 bfa_sm_fault(ioc, event);
551 }
552}
553
554
555static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700556bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -0700557{
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800558 bfa_trc(ioc, 0);
Jing Huang7725ccf2009-09-23 17:46:15 -0700559}
560
Jing Huang5fbe25c2010-10-18 17:17:23 -0700561/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700562 * IOC failure.
Jing Huang7725ccf2009-09-23 17:46:15 -0700563 */
564static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700565bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
Jing Huang7725ccf2009-09-23 17:46:15 -0700566{
567 bfa_trc(ioc, event);
568
569 switch (event) {
570
571 case IOC_E_ENABLE:
572 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
573 break;
574
575 case IOC_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700576 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Jing Huang7725ccf2009-09-23 17:46:15 -0700577 break;
578
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800579 case IOC_E_DETACH:
580 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
581 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
582 break;
583
Krishna Gudipati0a20de42010-03-05 19:34:20 -0800584 case IOC_E_HWERROR:
585 /*
586 * HB failure notification, ignore.
587 */
588 break;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700589 default:
590 bfa_sm_fault(ioc, event);
591 }
592}
593
Jing Huang5fbe25c2010-10-18 17:17:23 -0700594/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700595 * IOCPF State Machine
596 */
597
Jing Huang5fbe25c2010-10-18 17:17:23 -0700598/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700599 * Reset entry actions -- initialize state machine
600 */
601static void
602bfa_iocpf_sm_reset_entry(struct bfa_iocpf_s *iocpf)
603{
Krishna Gudipati775c7742011-06-13 15:52:12 -0700604 iocpf->fw_mismatch_notified = BFA_FALSE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700605 iocpf->auto_recover = bfa_auto_recover;
606}
607
Jing Huang5fbe25c2010-10-18 17:17:23 -0700608/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700609 * Beginning state. IOC is in reset state.
610 */
611static void
612bfa_iocpf_sm_reset(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
613{
614 struct bfa_ioc_s *ioc = iocpf->ioc;
615
616 bfa_trc(ioc, event);
617
618 switch (event) {
619 case IOCPF_E_ENABLE:
620 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
621 break;
622
623 case IOCPF_E_STOP:
624 break;
625
626 default:
627 bfa_sm_fault(ioc, event);
628 }
629}
630
Jing Huang5fbe25c2010-10-18 17:17:23 -0700631/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700632 * Semaphore should be acquired for version check.
633 */
634static void
635bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf)
636{
637 bfa_ioc_hw_sem_get(iocpf->ioc);
638}
639
Jing Huang5fbe25c2010-10-18 17:17:23 -0700640/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700641 * Awaiting h/w semaphore to continue with version check.
642 */
643static void
644bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
645{
646 struct bfa_ioc_s *ioc = iocpf->ioc;
647
648 bfa_trc(ioc, event);
649
650 switch (event) {
651 case IOCPF_E_SEMLOCKED:
652 if (bfa_ioc_firmware_lock(ioc)) {
Jing Huang45d7f0c2011-04-13 11:45:53 -0700653 if (bfa_ioc_sync_start(ioc)) {
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800654 bfa_ioc_sync_join(ioc);
655 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
656 } else {
657 bfa_ioc_firmware_unlock(ioc);
658 writel(1, ioc->ioc_regs.ioc_sem_reg);
659 bfa_sem_timer_start(ioc);
660 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700661 } else {
Maggie Zhangf7f73812010-12-09 19:08:43 -0800662 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700663 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
664 }
665 break;
666
667 case IOCPF_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800668 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700669 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800670 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700671 break;
672
673 case IOCPF_E_STOP:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800674 bfa_sem_timer_stop(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700675 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
676 break;
677
678 default:
679 bfa_sm_fault(ioc, event);
680 }
681}
682
Jing Huang5fbe25c2010-10-18 17:17:23 -0700683/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700684 * Notify enable completion callback.
685 */
686static void
687bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf_s *iocpf)
688{
689 /*
690 * Call only the first time sm enters fwmismatch state.
691 */
Krishna Gudipati775c7742011-06-13 15:52:12 -0700692 if (iocpf->fw_mismatch_notified == BFA_FALSE)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700693 bfa_ioc_pf_fwmismatch(iocpf->ioc);
694
Krishna Gudipati775c7742011-06-13 15:52:12 -0700695 iocpf->fw_mismatch_notified = BFA_TRUE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700696 bfa_iocpf_timer_start(iocpf->ioc);
697}
698
Jing Huang5fbe25c2010-10-18 17:17:23 -0700699/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700700 * Awaiting firmware version match.
701 */
702static void
703bfa_iocpf_sm_mismatch(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
704{
705 struct bfa_ioc_s *ioc = iocpf->ioc;
706
707 bfa_trc(ioc, event);
708
709 switch (event) {
710 case IOCPF_E_TIMEOUT:
711 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
712 break;
713
714 case IOCPF_E_DISABLE:
715 bfa_iocpf_timer_stop(ioc);
716 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800717 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700718 break;
719
720 case IOCPF_E_STOP:
721 bfa_iocpf_timer_stop(ioc);
722 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
723 break;
724
725 default:
726 bfa_sm_fault(ioc, event);
727 }
728}
729
Jing Huang5fbe25c2010-10-18 17:17:23 -0700730/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700731 * Request for semaphore.
732 */
733static void
734bfa_iocpf_sm_semwait_entry(struct bfa_iocpf_s *iocpf)
735{
736 bfa_ioc_hw_sem_get(iocpf->ioc);
737}
738
Jing Huang5fbe25c2010-10-18 17:17:23 -0700739/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700740 * Awaiting semaphore for h/w initialzation.
741 */
742static void
743bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
744{
745 struct bfa_ioc_s *ioc = iocpf->ioc;
746
747 bfa_trc(ioc, event);
748
749 switch (event) {
750 case IOCPF_E_SEMLOCKED:
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800751 if (bfa_ioc_sync_complete(ioc)) {
752 bfa_ioc_sync_join(ioc);
753 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
754 } else {
755 writel(1, ioc->ioc_regs.ioc_sem_reg);
756 bfa_sem_timer_start(ioc);
757 }
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700758 break;
759
760 case IOCPF_E_DISABLE:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800761 bfa_sem_timer_stop(ioc);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800762 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700763 break;
764
765 default:
766 bfa_sm_fault(ioc, event);
767 }
768}
769
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700770static void
771bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf_s *iocpf)
772{
Krishna Gudipati775c7742011-06-13 15:52:12 -0700773 iocpf->poll_time = 0;
Maggie Zhangf7f73812010-12-09 19:08:43 -0800774 bfa_ioc_hwinit(iocpf->ioc, BFA_FALSE);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700775}
776
Jing Huang5fbe25c2010-10-18 17:17:23 -0700777/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700778 * Hardware is being initialized. Interrupts are enabled.
779 * Holding hardware semaphore lock.
780 */
781static void
782bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
783{
784 struct bfa_ioc_s *ioc = iocpf->ioc;
785
786 bfa_trc(ioc, event);
787
788 switch (event) {
789 case IOCPF_E_FWREADY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700790 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
791 break;
792
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700793 case IOCPF_E_TIMEOUT:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800794 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700795 bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800796 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700797 break;
798
799 case IOCPF_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700800 bfa_iocpf_timer_stop(ioc);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800801 bfa_ioc_sync_leave(ioc);
802 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700803 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
804 break;
805
806 default:
807 bfa_sm_fault(ioc, event);
808 }
809}
810
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700811static void
812bfa_iocpf_sm_enabling_entry(struct bfa_iocpf_s *iocpf)
813{
814 bfa_iocpf_timer_start(iocpf->ioc);
Krishna Gudipati775c7742011-06-13 15:52:12 -0700815 /*
816 * Enable Interrupts before sending fw IOC ENABLE cmd.
817 */
818 iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700819 bfa_ioc_send_enable(iocpf->ioc);
820}
821
Jing Huang5fbe25c2010-10-18 17:17:23 -0700822/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700823 * Host IOC function is being enabled, awaiting response from firmware.
824 * Semaphore is acquired.
825 */
826static void
827bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
828{
829 struct bfa_ioc_s *ioc = iocpf->ioc;
830
831 bfa_trc(ioc, event);
832
833 switch (event) {
834 case IOCPF_E_FWRSP_ENABLE:
835 bfa_iocpf_timer_stop(ioc);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800836 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700837 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
838 break;
839
840 case IOCPF_E_INITFAIL:
841 bfa_iocpf_timer_stop(ioc);
842 /*
843 * !!! fall through !!!
844 */
845
846 case IOCPF_E_TIMEOUT:
Maggie Zhangf7f73812010-12-09 19:08:43 -0800847 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700848 if (event == IOCPF_E_TIMEOUT)
Krishna Gudipati4e78efe2010-12-13 16:16:09 -0800849 bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800850 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700851 break;
852
853 case IOCPF_E_DISABLE:
854 bfa_iocpf_timer_stop(ioc);
Maggie Zhangf7f73812010-12-09 19:08:43 -0800855 writel(1, ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700856 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
857 break;
858
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700859 default:
860 bfa_sm_fault(ioc, event);
861 }
862}
863
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700864static void
865bfa_iocpf_sm_ready_entry(struct bfa_iocpf_s *iocpf)
866{
Maggie Zhangf7f73812010-12-09 19:08:43 -0800867 bfa_fsm_send_event(iocpf->ioc, IOC_E_ENABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700868}
869
870static void
871bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
872{
873 struct bfa_ioc_s *ioc = iocpf->ioc;
874
875 bfa_trc(ioc, event);
876
877 switch (event) {
878 case IOCPF_E_DISABLE:
879 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
880 break;
881
882 case IOCPF_E_GETATTRFAIL:
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800883 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700884 break;
885
886 case IOCPF_E_FAIL:
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800887 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700888 break;
889
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700890 default:
891 bfa_sm_fault(ioc, event);
892 }
893}
894
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700895static void
896bfa_iocpf_sm_disabling_entry(struct bfa_iocpf_s *iocpf)
897{
898 bfa_iocpf_timer_start(iocpf->ioc);
899 bfa_ioc_send_disable(iocpf->ioc);
900}
901
Jing Huang5fbe25c2010-10-18 17:17:23 -0700902/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700903 * IOC is being disabled
904 */
905static void
906bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
907{
908 struct bfa_ioc_s *ioc = iocpf->ioc;
909
910 bfa_trc(ioc, event);
911
912 switch (event) {
913 case IOCPF_E_FWRSP_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700914 bfa_iocpf_timer_stop(ioc);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800915 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700916 break;
917
918 case IOCPF_E_FAIL:
919 bfa_iocpf_timer_stop(ioc);
920 /*
921 * !!! fall through !!!
922 */
923
924 case IOCPF_E_TIMEOUT:
Jing Huang53440262010-10-18 17:12:29 -0700925 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800926 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700927 break;
928
929 case IOCPF_E_FWRSP_ENABLE:
930 break;
931
932 default:
933 bfa_sm_fault(ioc, event);
934 }
935}
936
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800937static void
938bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf)
939{
940 bfa_ioc_hw_sem_get(iocpf->ioc);
941}
942
Jing Huang8f4bfad2010-12-26 21:50:10 -0800943/*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -0800944 * IOC hb ack request is being removed.
945 */
946static void
947bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
948{
949 struct bfa_ioc_s *ioc = iocpf->ioc;
950
951 bfa_trc(ioc, event);
952
953 switch (event) {
954 case IOCPF_E_SEMLOCKED:
955 bfa_ioc_sync_leave(ioc);
956 writel(1, ioc->ioc_regs.ioc_sem_reg);
957 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
958 break;
959
960 case IOCPF_E_FAIL:
961 break;
962
963 default:
964 bfa_sm_fault(ioc, event);
965 }
966}
967
Jing Huang5fbe25c2010-10-18 17:17:23 -0700968/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700969 * IOC disable completion entry.
970 */
971static void
972bfa_iocpf_sm_disabled_entry(struct bfa_iocpf_s *iocpf)
973{
Maggie Zhangf7f73812010-12-09 19:08:43 -0800974 bfa_fsm_send_event(iocpf->ioc, IOC_E_DISABLED);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700975}
976
977static void
978bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
979{
980 struct bfa_ioc_s *ioc = iocpf->ioc;
981
982 bfa_trc(ioc, event);
983
984 switch (event) {
985 case IOCPF_E_ENABLE:
986 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
987 break;
988
989 case IOCPF_E_STOP:
990 bfa_ioc_firmware_unlock(ioc);
991 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
992 break;
993
994 default:
995 bfa_sm_fault(ioc, event);
996 }
997}
998
Krishna Gudipatia36c61f2010-09-15 11:50:55 -0700999static void
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001000bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf)
1001{
1002 bfa_ioc_hw_sem_get(iocpf->ioc);
1003}
1004
Jing Huang8f4bfad2010-12-26 21:50:10 -08001005/*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001006 * Hardware initialization failed.
1007 */
1008static void
1009bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1010{
1011 struct bfa_ioc_s *ioc = iocpf->ioc;
1012
1013 bfa_trc(ioc, event);
1014
1015 switch (event) {
1016 case IOCPF_E_SEMLOCKED:
1017 bfa_ioc_notify_fail(ioc);
Krishna Gudipati775c7742011-06-13 15:52:12 -07001018 bfa_ioc_sync_leave(ioc);
1019 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1020 writel(1, ioc->ioc_regs.ioc_sem_reg);
1021 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001022 break;
1023
1024 case IOCPF_E_DISABLE:
1025 bfa_sem_timer_stop(ioc);
1026 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1027 break;
1028
1029 case IOCPF_E_STOP:
1030 bfa_sem_timer_stop(ioc);
1031 bfa_ioc_firmware_unlock(ioc);
1032 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1033 break;
1034
1035 case IOCPF_E_FAIL:
1036 break;
1037
1038 default:
1039 bfa_sm_fault(ioc, event);
1040 }
1041}
1042
1043static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001044bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf)
1045{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001046}
1047
Jing Huang5fbe25c2010-10-18 17:17:23 -07001048/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001049 * Hardware initialization failed.
1050 */
1051static void
1052bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1053{
1054 struct bfa_ioc_s *ioc = iocpf->ioc;
1055
1056 bfa_trc(ioc, event);
1057
1058 switch (event) {
1059 case IOCPF_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001060 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1061 break;
1062
1063 case IOCPF_E_STOP:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001064 bfa_ioc_firmware_unlock(ioc);
1065 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1066 break;
1067
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001068 default:
1069 bfa_sm_fault(ioc, event);
1070 }
1071}
1072
1073static void
1074bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf)
1075{
Jing Huang8f4bfad2010-12-26 21:50:10 -08001076 /*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001077 * Mark IOC as failed in hardware and stop firmware.
1078 */
1079 bfa_ioc_lpu_stop(iocpf->ioc);
1080
Jing Huang8f4bfad2010-12-26 21:50:10 -08001081 /*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001082 * Flush any queued up mailbox requests.
1083 */
1084 bfa_ioc_mbox_hbfail(iocpf->ioc);
1085
1086 bfa_ioc_hw_sem_get(iocpf->ioc);
1087}
1088
1089static void
1090bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1091{
1092 struct bfa_ioc_s *ioc = iocpf->ioc;
1093
1094 bfa_trc(ioc, event);
1095
1096 switch (event) {
1097 case IOCPF_E_SEMLOCKED:
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001098 bfa_ioc_sync_ack(ioc);
1099 bfa_ioc_notify_fail(ioc);
1100 if (!iocpf->auto_recover) {
1101 bfa_ioc_sync_leave(ioc);
Krishna Gudipati775c7742011-06-13 15:52:12 -07001102 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08001103 writel(1, ioc->ioc_regs.ioc_sem_reg);
1104 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1105 } else {
1106 if (bfa_ioc_sync_complete(ioc))
1107 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
1108 else {
1109 writel(1, ioc->ioc_regs.ioc_sem_reg);
1110 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1111 }
1112 }
1113 break;
1114
1115 case IOCPF_E_DISABLE:
1116 bfa_sem_timer_stop(ioc);
1117 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1118 break;
1119
1120 case IOCPF_E_FAIL:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001121 break;
1122
1123 default:
1124 bfa_sm_fault(ioc, event);
1125 }
1126}
1127
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001128static void
1129bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf)
1130{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001131}
1132
Jing Huang5fbe25c2010-10-18 17:17:23 -07001133/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001134 * IOC is in failed state.
1135 */
1136static void
1137bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
1138{
1139 struct bfa_ioc_s *ioc = iocpf->ioc;
1140
1141 bfa_trc(ioc, event);
1142
1143 switch (event) {
1144 case IOCPF_E_DISABLE:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001145 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1146 break;
1147
Jing Huang7725ccf2009-09-23 17:46:15 -07001148 default:
1149 bfa_sm_fault(ioc, event);
1150 }
1151}
1152
Jing Huang5fbe25c2010-10-18 17:17:23 -07001153/*
Maggie Zhangdf0f1932010-12-09 19:07:46 -08001154 * BFA IOC private functions
Jing Huang7725ccf2009-09-23 17:46:15 -07001155 */
1156
Krishna Gudipatid37779f2011-06-13 15:42:10 -07001157/*
1158 * Notify common modules registered for notification.
1159 */
1160static void
1161bfa_ioc_event_notify(struct bfa_ioc_s *ioc, enum bfa_ioc_event_e event)
1162{
1163 struct bfa_ioc_notify_s *notify;
1164 struct list_head *qe;
1165
1166 list_for_each(qe, &ioc->notify_q) {
1167 notify = (struct bfa_ioc_notify_s *)qe;
1168 notify->cbfn(notify->cbarg, event);
1169 }
1170}
1171
Jing Huang7725ccf2009-09-23 17:46:15 -07001172static void
1173bfa_ioc_disable_comp(struct bfa_ioc_s *ioc)
1174{
Jing Huang7725ccf2009-09-23 17:46:15 -07001175 ioc->cbfn->disable_cbfn(ioc->bfa);
Krishna Gudipatid37779f2011-06-13 15:42:10 -07001176 bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
Jing Huang7725ccf2009-09-23 17:46:15 -07001177}
1178
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001179bfa_boolean_t
Jing Huang53440262010-10-18 17:12:29 -07001180bfa_ioc_sem_get(void __iomem *sem_reg)
Jing Huang7725ccf2009-09-23 17:46:15 -07001181{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001182 u32 r32;
1183 int cnt = 0;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001184#define BFA_SEM_SPINCNT 3000
Jing Huang7725ccf2009-09-23 17:46:15 -07001185
Jing Huang53440262010-10-18 17:12:29 -07001186 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001187
Krishna Gudipati11189202011-06-13 15:50:35 -07001188 while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001189 cnt++;
Jing Huang6a18b162010-10-18 17:08:54 -07001190 udelay(2);
Jing Huang53440262010-10-18 17:12:29 -07001191 r32 = readl(sem_reg);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001192 }
1193
Krishna Gudipati11189202011-06-13 15:50:35 -07001194 if (!(r32 & 1))
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001195 return BFA_TRUE;
1196
Jing Huangd4b671c2010-12-26 21:46:35 -08001197 WARN_ON(cnt >= BFA_SEM_SPINCNT);
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001198 return BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001199}
1200
Jing Huang7725ccf2009-09-23 17:46:15 -07001201static void
1202bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc)
1203{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001204 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001205
Jing Huang5fbe25c2010-10-18 17:17:23 -07001206 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001207 * First read to the semaphore register will return 0, subsequent reads
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001208 * will return 1. Semaphore is released by writing 1 to the register
Jing Huang7725ccf2009-09-23 17:46:15 -07001209 */
Jing Huang53440262010-10-18 17:12:29 -07001210 r32 = readl(ioc->ioc_regs.ioc_sem_reg);
Krishna Gudipati11189202011-06-13 15:50:35 -07001211 if (!(r32 & 1)) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001212 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
Jing Huang7725ccf2009-09-23 17:46:15 -07001213 return;
1214 }
1215
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001216 bfa_sem_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001217}
1218
Jing Huang5fbe25c2010-10-18 17:17:23 -07001219/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001220 * Initialize LPU local memory (aka secondary memory / SRAM)
1221 */
1222static void
1223bfa_ioc_lmem_init(struct bfa_ioc_s *ioc)
1224{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001225 u32 pss_ctl;
1226 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001227#define PSS_LMEM_INIT_TIME 10000
1228
Jing Huang53440262010-10-18 17:12:29 -07001229 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001230 pss_ctl &= ~__PSS_LMEM_RESET;
1231 pss_ctl |= __PSS_LMEM_INIT_EN;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001232
1233 /*
1234 * i2c workaround 12.5khz clock
1235 */
1236 pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
Jing Huang53440262010-10-18 17:12:29 -07001237 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001238
Jing Huang5fbe25c2010-10-18 17:17:23 -07001239 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001240 * wait for memory initialization to be complete
1241 */
1242 i = 0;
1243 do {
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 i++;
1246 } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1247
Jing Huang5fbe25c2010-10-18 17:17:23 -07001248 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001249 * If memory initialization is not successful, IOC timeout will catch
1250 * such failures.
1251 */
Jing Huangd4b671c2010-12-26 21:46:35 -08001252 WARN_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
Jing Huang7725ccf2009-09-23 17:46:15 -07001253 bfa_trc(ioc, pss_ctl);
1254
1255 pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
Jing Huang53440262010-10-18 17:12:29 -07001256 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001257}
1258
1259static void
1260bfa_ioc_lpu_start(struct bfa_ioc_s *ioc)
1261{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001262 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001263
Jing Huang5fbe25c2010-10-18 17:17:23 -07001264 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001265 * Take processor out of reset.
1266 */
Jing Huang53440262010-10-18 17:12:29 -07001267 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001268 pss_ctl &= ~__PSS_LPU0_RESET;
1269
Jing Huang53440262010-10-18 17:12:29 -07001270 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001271}
1272
1273static void
1274bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc)
1275{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001276 u32 pss_ctl;
Jing Huang7725ccf2009-09-23 17:46:15 -07001277
Jing Huang5fbe25c2010-10-18 17:17:23 -07001278 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001279 * Put processors in reset.
1280 */
Jing Huang53440262010-10-18 17:12:29 -07001281 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001282 pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1283
Jing Huang53440262010-10-18 17:12:29 -07001284 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
Jing Huang7725ccf2009-09-23 17:46:15 -07001285}
1286
Jing Huang5fbe25c2010-10-18 17:17:23 -07001287/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001288 * Get driver and firmware versions.
1289 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001290void
Jing Huang7725ccf2009-09-23 17:46:15 -07001291bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1292{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001293 u32 pgnum, pgoff;
1294 u32 loff = 0;
1295 int i;
1296 u32 *fwsig = (u32 *) fwhdr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001297
Maggie Zhangf7f73812010-12-09 19:08:43 -08001298 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1299 pgoff = PSS_SMEM_PGOFF(loff);
Jing Huang53440262010-10-18 17:12:29 -07001300 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001301
1302 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32));
1303 i++) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001304 fwsig[i] =
1305 bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001306 loff += sizeof(u32);
1307 }
1308}
1309
Jing Huang5fbe25c2010-10-18 17:17:23 -07001310/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001311 * Returns TRUE if same.
1312 */
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001313bfa_boolean_t
Jing Huang7725ccf2009-09-23 17:46:15 -07001314bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1315{
1316 struct bfi_ioc_image_hdr_s *drv_fwhdr;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001317 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001318
Jing Huang293f82d2010-07-08 19:45:20 -07001319 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipati11189202011-06-13 15:50:35 -07001320 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001321
1322 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1323 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) {
1324 bfa_trc(ioc, i);
1325 bfa_trc(ioc, fwhdr->md5sum[i]);
1326 bfa_trc(ioc, drv_fwhdr->md5sum[i]);
1327 return BFA_FALSE;
1328 }
1329 }
1330
1331 bfa_trc(ioc, fwhdr->md5sum[0]);
1332 return BFA_TRUE;
1333}
1334
Jing Huang5fbe25c2010-10-18 17:17:23 -07001335/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001336 * Return true if current running version is valid. Firmware signature and
1337 * execution context (driver/bios) must match.
1338 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001339static bfa_boolean_t
1340bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001341{
1342 struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr;
1343
Jing Huang7725ccf2009-09-23 17:46:15 -07001344 bfa_ioc_fwver_get(ioc, &fwhdr);
Jing Huang293f82d2010-07-08 19:45:20 -07001345 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
Krishna Gudipati11189202011-06-13 15:50:35 -07001346 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
Jing Huang7725ccf2009-09-23 17:46:15 -07001347
1348 if (fwhdr.signature != drv_fwhdr->signature) {
1349 bfa_trc(ioc, fwhdr.signature);
1350 bfa_trc(ioc, drv_fwhdr->signature);
1351 return BFA_FALSE;
1352 }
1353
Krishna Gudipati11189202011-06-13 15:50:35 -07001354 if (swab32(fwhdr.bootenv) != boot_env) {
1355 bfa_trc(ioc, fwhdr.bootenv);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001356 bfa_trc(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001357 return BFA_FALSE;
1358 }
1359
1360 return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1361}
1362
Jing Huang5fbe25c2010-10-18 17:17:23 -07001363/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001364 * Conditionally flush any pending message from firmware at start.
1365 */
1366static void
1367bfa_ioc_msgflush(struct bfa_ioc_s *ioc)
1368{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001369 u32 r32;
Jing Huang7725ccf2009-09-23 17:46:15 -07001370
Jing Huang53440262010-10-18 17:12:29 -07001371 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001372 if (r32)
Jing Huang53440262010-10-18 17:12:29 -07001373 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001374}
1375
Jing Huang7725ccf2009-09-23 17:46:15 -07001376static void
1377bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1378{
1379 enum bfi_ioc_state ioc_fwstate;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001380 bfa_boolean_t fwvalid;
1381 u32 boot_type;
1382 u32 boot_env;
Jing Huang7725ccf2009-09-23 17:46:15 -07001383
Jing Huang53440262010-10-18 17:12:29 -07001384 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07001385
1386 if (force)
1387 ioc_fwstate = BFI_IOC_UNINIT;
1388
1389 bfa_trc(ioc, ioc_fwstate);
1390
Krishna Gudipati11189202011-06-13 15:50:35 -07001391 boot_type = BFI_FWBOOT_TYPE_NORMAL;
1392 boot_env = BFI_FWBOOT_ENV_OS;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001393
Jing Huang5fbe25c2010-10-18 17:17:23 -07001394 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001395 * check if firmware is valid
1396 */
1397 fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001398 BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001399
1400 if (!fwvalid) {
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001401 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001402 return;
1403 }
1404
Jing Huang5fbe25c2010-10-18 17:17:23 -07001405 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001406 * If hardware initialization is in progress (initialized by other IOC),
1407 * just wait for an initialization completion interrupt.
1408 */
1409 if (ioc_fwstate == BFI_IOC_INITING) {
Krishna Gudipati775c7742011-06-13 15:52:12 -07001410 bfa_ioc_poll_fwinit(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001411 return;
1412 }
1413
Jing Huang5fbe25c2010-10-18 17:17:23 -07001414 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001415 * If IOC function is disabled and firmware version is same,
1416 * just re-enable IOC.
Jing Huang07b28382010-07-08 19:59:24 -07001417 *
1418 * If option rom, IOC must not be in operational state. With
1419 * convergence, IOC will be in operational state when 2nd driver
1420 * is loaded.
Jing Huang7725ccf2009-09-23 17:46:15 -07001421 */
Jing Huang8f4bfad2010-12-26 21:50:10 -08001422 if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001423
Jing Huang5fbe25c2010-10-18 17:17:23 -07001424 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001425 * When using MSI-X any pending firmware ready event should
1426 * be flushed. Otherwise MSI-X interrupts are not delivered.
1427 */
1428 bfa_ioc_msgflush(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001429 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
Jing Huang7725ccf2009-09-23 17:46:15 -07001430 return;
1431 }
1432
Jing Huang5fbe25c2010-10-18 17:17:23 -07001433 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001434 * Initialize the h/w for any other states.
1435 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001436 bfa_ioc_boot(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001437}
1438
1439static void
1440bfa_ioc_timeout(void *ioc_arg)
1441{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001442 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
Jing Huang7725ccf2009-09-23 17:46:15 -07001443
1444 bfa_trc(ioc, 0);
1445 bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1446}
1447
1448void
1449bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len)
1450{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001451 u32 *msgp = (u32 *) ioc_msg;
1452 u32 i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001453
1454 bfa_trc(ioc, msgp[0]);
1455 bfa_trc(ioc, len);
1456
Jing Huangd4b671c2010-12-26 21:46:35 -08001457 WARN_ON(len > BFI_IOC_MSGLEN_MAX);
Jing Huang7725ccf2009-09-23 17:46:15 -07001458
1459 /*
1460 * first write msg to mailbox registers
1461 */
1462 for (i = 0; i < len / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001463 writel(cpu_to_le32(msgp[i]),
1464 ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001465
1466 for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
Jing Huang53440262010-10-18 17:12:29 -07001467 writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
Jing Huang7725ccf2009-09-23 17:46:15 -07001468
1469 /*
1470 * write 1 to mailbox CMD to trigger LPU event
1471 */
Jing Huang53440262010-10-18 17:12:29 -07001472 writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1473 (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001474}
1475
1476static void
1477bfa_ioc_send_enable(struct bfa_ioc_s *ioc)
1478{
1479 struct bfi_ioc_ctrl_req_s enable_req;
Maggie Zhangf16a1752010-12-09 19:12:32 -08001480 struct timeval tv;
Jing Huang7725ccf2009-09-23 17:46:15 -07001481
1482 bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1483 bfa_ioc_portid(ioc));
Krishna Gudipatid37779f2011-06-13 15:42:10 -07001484 enable_req.clscode = cpu_to_be16(ioc->clscode);
Maggie Zhangf16a1752010-12-09 19:12:32 -08001485 do_gettimeofday(&tv);
Jing Huangba816ea2010-10-18 17:10:50 -07001486 enable_req.tv_sec = be32_to_cpu(tv.tv_sec);
Jing Huang7725ccf2009-09-23 17:46:15 -07001487 bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1488}
1489
1490static void
1491bfa_ioc_send_disable(struct bfa_ioc_s *ioc)
1492{
1493 struct bfi_ioc_ctrl_req_s disable_req;
1494
1495 bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1496 bfa_ioc_portid(ioc));
1497 bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s));
1498}
1499
1500static void
1501bfa_ioc_send_getattr(struct bfa_ioc_s *ioc)
1502{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001503 struct bfi_ioc_getattr_req_s attr_req;
Jing Huang7725ccf2009-09-23 17:46:15 -07001504
1505 bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1506 bfa_ioc_portid(ioc));
1507 bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1508 bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1509}
1510
1511static void
1512bfa_ioc_hb_check(void *cbarg)
1513{
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001514 struct bfa_ioc_s *ioc = cbarg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001515 u32 hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001516
Jing Huang53440262010-10-18 17:12:29 -07001517 hb_count = readl(ioc->ioc_regs.heartbeat);
Jing Huang7725ccf2009-09-23 17:46:15 -07001518 if (ioc->hb_count == hb_count) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001519 bfa_ioc_recover(ioc);
1520 return;
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001521 } else {
1522 ioc->hb_count = hb_count;
Jing Huang7725ccf2009-09-23 17:46:15 -07001523 }
1524
1525 bfa_ioc_mbox_poll(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001526 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001527}
1528
1529static void
1530bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1531{
Jing Huang53440262010-10-18 17:12:29 -07001532 ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001533 bfa_hb_timer_start(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07001534}
1535
Jing Huang5fbe25c2010-10-18 17:17:23 -07001536/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001537 * Initiate a full firmware download.
Jing Huang7725ccf2009-09-23 17:46:15 -07001538 */
1539static void
1540bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001541 u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001542{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001543 u32 *fwimg;
1544 u32 pgnum, pgoff;
1545 u32 loff = 0;
1546 u32 chunkno = 0;
1547 u32 i;
Krishna Gudipati11189202011-06-13 15:50:35 -07001548 u32 asicmode;
Jing Huang7725ccf2009-09-23 17:46:15 -07001549
Jing Huang5fbe25c2010-10-18 17:17:23 -07001550 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001551 * Initialize LMEM first before code download
1552 */
1553 bfa_ioc_lmem_init(ioc);
1554
Krishna Gudipati11189202011-06-13 15:50:35 -07001555 bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
1556 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
Jing Huang7725ccf2009-09-23 17:46:15 -07001557
Maggie Zhangf7f73812010-12-09 19:08:43 -08001558 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1559 pgoff = PSS_SMEM_PGOFF(loff);
Jing Huang7725ccf2009-09-23 17:46:15 -07001560
Jing Huang53440262010-10-18 17:12:29 -07001561 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001562
Krishna Gudipati11189202011-06-13 15:50:35 -07001563 for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
Jing Huang7725ccf2009-09-23 17:46:15 -07001564
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001565 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1566 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
Krishna Gudipati11189202011-06-13 15:50:35 -07001567 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001568 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
Jing Huang7725ccf2009-09-23 17:46:15 -07001569 }
1570
Jing Huang5fbe25c2010-10-18 17:17:23 -07001571 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001572 * write smem
1573 */
1574 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
Krishna Gudipati0a20de42010-03-05 19:34:20 -08001575 fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
Jing Huang7725ccf2009-09-23 17:46:15 -07001576
1577 loff += sizeof(u32);
1578
Jing Huang5fbe25c2010-10-18 17:17:23 -07001579 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001580 * handle page offset wrap around
1581 */
1582 loff = PSS_SMEM_PGOFF(loff);
1583 if (loff == 0) {
1584 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001585 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Jing Huang7725ccf2009-09-23 17:46:15 -07001586 }
1587 }
1588
Maggie Zhangf7f73812010-12-09 19:08:43 -08001589 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1590 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipati13cc20c2010-03-05 19:37:29 -08001591
1592 /*
Krishna Gudipati11189202011-06-13 15:50:35 -07001593 * Set boot type and device mode at the end.
1594 */
1595 asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
1596 ioc->port0_mode, ioc->port1_mode);
1597 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
1598 swab32(asicmode));
1599 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_TYPE_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001600 swab32(boot_type));
Krishna Gudipati11189202011-06-13 15:50:35 -07001601 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
Jing Huang53440262010-10-18 17:12:29 -07001602 swab32(boot_env));
Jing Huang7725ccf2009-09-23 17:46:15 -07001603}
1604
Jing Huang7725ccf2009-09-23 17:46:15 -07001605
Jing Huang5fbe25c2010-10-18 17:17:23 -07001606/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001607 * Update BFA configuration from firmware configuration.
1608 */
1609static void
1610bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc)
1611{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001612 struct bfi_ioc_attr_s *attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07001613
Jing Huangba816ea2010-10-18 17:10:50 -07001614 attr->adapter_prop = be32_to_cpu(attr->adapter_prop);
1615 attr->card_type = be32_to_cpu(attr->card_type);
1616 attr->maxfrsize = be16_to_cpu(attr->maxfrsize);
Jing Huang7725ccf2009-09-23 17:46:15 -07001617
1618 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1619}
1620
Jing Huang5fbe25c2010-10-18 17:17:23 -07001621/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001622 * Attach time initialization of mbox logic.
1623 */
1624static void
1625bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc)
1626{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001627 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1628 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001629
1630 INIT_LIST_HEAD(&mod->cmd_q);
1631 for (mc = 0; mc < BFI_MC_MAX; mc++) {
1632 mod->mbhdlr[mc].cbfn = NULL;
1633 mod->mbhdlr[mc].cbarg = ioc->bfa;
1634 }
1635}
1636
Jing Huang5fbe25c2010-10-18 17:17:23 -07001637/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001638 * Mbox poll timer -- restarts any pending mailbox requests.
1639 */
1640static void
1641bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc)
1642{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001643 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1644 struct bfa_mbox_cmd_s *cmd;
1645 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07001646
Jing Huang5fbe25c2010-10-18 17:17:23 -07001647 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001648 * If no command pending, do nothing
1649 */
1650 if (list_empty(&mod->cmd_q))
1651 return;
1652
Jing Huang5fbe25c2010-10-18 17:17:23 -07001653 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001654 * If previous command is not yet fetched by firmware, do nothing
1655 */
Jing Huang53440262010-10-18 17:12:29 -07001656 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07001657 if (stat)
1658 return;
1659
Jing Huang5fbe25c2010-10-18 17:17:23 -07001660 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001661 * Enqueue command to firmware.
1662 */
1663 bfa_q_deq(&mod->cmd_q, &cmd);
1664 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1665}
1666
Jing Huang5fbe25c2010-10-18 17:17:23 -07001667/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001668 * Cleanup any pending requests.
1669 */
1670static void
1671bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc)
1672{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001673 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
1674 struct bfa_mbox_cmd_s *cmd;
Jing Huang7725ccf2009-09-23 17:46:15 -07001675
1676 while (!list_empty(&mod->cmd_q))
1677 bfa_q_deq(&mod->cmd_q, &cmd);
1678}
1679
Jing Huang5fbe25c2010-10-18 17:17:23 -07001680/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001681 * Read data from SMEM to host through PCI memmap
1682 *
1683 * @param[in] ioc memory for IOC
1684 * @param[in] tbuf app memory to store data from smem
1685 * @param[in] soff smem offset
1686 * @param[in] sz size of smem in bytes
Jing Huang7725ccf2009-09-23 17:46:15 -07001687 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001688static bfa_status_t
1689bfa_ioc_smem_read(struct bfa_ioc_s *ioc, void *tbuf, u32 soff, u32 sz)
1690{
Maggie50444a32010-11-29 18:26:32 -08001691 u32 pgnum, loff;
1692 __be32 r32;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001693 int i, len;
1694 u32 *buf = tbuf;
1695
Maggie Zhangf7f73812010-12-09 19:08:43 -08001696 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1697 loff = PSS_SMEM_PGOFF(soff);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001698 bfa_trc(ioc, pgnum);
1699 bfa_trc(ioc, loff);
1700 bfa_trc(ioc, sz);
1701
1702 /*
1703 * Hold semaphore to serialize pll init and fwtrc.
1704 */
1705 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1706 bfa_trc(ioc, 0);
1707 return BFA_STATUS_FAILED;
1708 }
1709
Jing Huang53440262010-10-18 17:12:29 -07001710 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001711
1712 len = sz/sizeof(u32);
1713 bfa_trc(ioc, len);
1714 for (i = 0; i < len; i++) {
1715 r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff);
Jing Huangba816ea2010-10-18 17:10:50 -07001716 buf[i] = be32_to_cpu(r32);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001717 loff += sizeof(u32);
1718
Jing Huang5fbe25c2010-10-18 17:17:23 -07001719 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001720 * handle page offset wrap around
1721 */
1722 loff = PSS_SMEM_PGOFF(loff);
1723 if (loff == 0) {
1724 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001725 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001726 }
1727 }
Maggie Zhangf7f73812010-12-09 19:08:43 -08001728 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1729 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001730 /*
1731 * release semaphore.
1732 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08001733 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001734
1735 bfa_trc(ioc, pgnum);
1736 return BFA_STATUS_OK;
1737}
1738
Jing Huang5fbe25c2010-10-18 17:17:23 -07001739/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001740 * Clear SMEM data from host through PCI memmap
1741 *
1742 * @param[in] ioc memory for IOC
1743 * @param[in] soff smem offset
1744 * @param[in] sz size of smem in bytes
1745 */
1746static bfa_status_t
1747bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
1748{
1749 int i, len;
1750 u32 pgnum, loff;
1751
Maggie Zhangf7f73812010-12-09 19:08:43 -08001752 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1753 loff = PSS_SMEM_PGOFF(soff);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001754 bfa_trc(ioc, pgnum);
1755 bfa_trc(ioc, loff);
1756 bfa_trc(ioc, sz);
1757
1758 /*
1759 * Hold semaphore to serialize pll init and fwtrc.
1760 */
1761 if (BFA_FALSE == bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg)) {
1762 bfa_trc(ioc, 0);
1763 return BFA_STATUS_FAILED;
1764 }
1765
Jing Huang53440262010-10-18 17:12:29 -07001766 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001767
1768 len = sz/sizeof(u32); /* len in words */
1769 bfa_trc(ioc, len);
1770 for (i = 0; i < len; i++) {
1771 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 0);
1772 loff += sizeof(u32);
1773
Jing Huang5fbe25c2010-10-18 17:17:23 -07001774 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001775 * handle page offset wrap around
1776 */
1777 loff = PSS_SMEM_PGOFF(loff);
1778 if (loff == 0) {
1779 pgnum++;
Jing Huang53440262010-10-18 17:12:29 -07001780 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001781 }
1782 }
Maggie Zhangf7f73812010-12-09 19:08:43 -08001783 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1784 ioc->ioc_regs.host_page_num_fn);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001785
1786 /*
1787 * release semaphore.
1788 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08001789 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001790 bfa_trc(ioc, pgnum);
1791 return BFA_STATUS_OK;
1792}
1793
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001794static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08001795bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
1796{
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08001797 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
1798
Jing Huang8f4bfad2010-12-26 21:50:10 -08001799 /*
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08001800 * Notify driver and common modules registered for notification.
1801 */
1802 ioc->cbfn->hbfail_cbfn(ioc->bfa);
Krishna Gudipatid37779f2011-06-13 15:42:10 -07001803 bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08001804
1805 bfa_ioc_debug_save_ftrc(ioc);
1806
1807 BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
1808 "Heart Beat of IOC has failed\n");
1809
1810}
1811
1812static void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001813bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
1814{
1815 struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
Jing Huang5fbe25c2010-10-18 17:17:23 -07001816 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001817 * Provide enable completion callback.
1818 */
1819 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Jing Huang88166242010-12-09 17:11:53 -08001820 BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001821 "Running firmware version is incompatible "
1822 "with the driver version\n");
1823}
1824
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001825bfa_status_t
1826bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
1827{
1828
1829 /*
1830 * Hold semaphore so that nobody can access the chip during init.
1831 */
1832 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1833
1834 bfa_ioc_pll_init_asic(ioc);
1835
1836 ioc->pllinit = BFA_TRUE;
1837 /*
1838 * release semaphore.
1839 */
Maggie Zhangf7f73812010-12-09 19:08:43 -08001840 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001841
1842 return BFA_STATUS_OK;
1843}
Jing Huang7725ccf2009-09-23 17:46:15 -07001844
Jing Huang5fbe25c2010-10-18 17:17:23 -07001845/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001846 * Interface used by diag module to do firmware boot with memory test
1847 * as the entry vector.
1848 */
1849void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001850bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
Jing Huang7725ccf2009-09-23 17:46:15 -07001851{
Jing Huang7725ccf2009-09-23 17:46:15 -07001852 bfa_ioc_stats(ioc, ioc_boots);
1853
1854 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1855 return;
1856
Jing Huang5fbe25c2010-10-18 17:17:23 -07001857 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001858 * Initialize IOC state of all functions on a chip reset.
1859 */
Krishna Gudipati11189202011-06-13 15:50:35 -07001860 if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
1861 writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
1862 writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07001863 } else {
Krishna Gudipati11189202011-06-13 15:50:35 -07001864 writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
1865 writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07001866 }
1867
Jing Huang07b28382010-07-08 19:59:24 -07001868 bfa_ioc_msgflush(ioc);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001869 bfa_ioc_download_fw(ioc, boot_type, boot_env);
Jing Huang7725ccf2009-09-23 17:46:15 -07001870 bfa_ioc_lpu_start(ioc);
1871}
1872
Jing Huang5fbe25c2010-10-18 17:17:23 -07001873/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001874 * Enable/disable IOC failure auto recovery.
1875 */
1876void
1877bfa_ioc_auto_recover(bfa_boolean_t auto_recover)
1878{
Krishna Gudipati2f9b8852010-03-03 17:42:51 -08001879 bfa_auto_recover = auto_recover;
Jing Huang7725ccf2009-09-23 17:46:15 -07001880}
1881
1882
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001883
Jing Huang7725ccf2009-09-23 17:46:15 -07001884bfa_boolean_t
1885bfa_ioc_is_operational(struct bfa_ioc_s *ioc)
1886{
1887 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
1888}
1889
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001890bfa_boolean_t
1891bfa_ioc_is_initialized(struct bfa_ioc_s *ioc)
1892{
Jing Huang53440262010-10-18 17:12:29 -07001893 u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001894
1895 return ((r32 != BFI_IOC_UNINIT) &&
1896 (r32 != BFI_IOC_INITING) &&
1897 (r32 != BFI_IOC_MEMTEST));
1898}
1899
Krishna Gudipati11189202011-06-13 15:50:35 -07001900bfa_boolean_t
Jing Huang7725ccf2009-09-23 17:46:15 -07001901bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg)
1902{
Maggie50444a32010-11-29 18:26:32 -08001903 __be32 *msgp = mbmsg;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001904 u32 r32;
1905 int i;
Jing Huang7725ccf2009-09-23 17:46:15 -07001906
Krishna Gudipati11189202011-06-13 15:50:35 -07001907 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
1908 if ((r32 & 1) == 0)
1909 return BFA_FALSE;
1910
Jing Huang5fbe25c2010-10-18 17:17:23 -07001911 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001912 * read the MBOX msg
1913 */
1914 for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
1915 i++) {
Jing Huang53440262010-10-18 17:12:29 -07001916 r32 = readl(ioc->ioc_regs.lpu_mbox +
Jing Huang7725ccf2009-09-23 17:46:15 -07001917 i * sizeof(u32));
Jing Huangba816ea2010-10-18 17:10:50 -07001918 msgp[i] = cpu_to_be32(r32);
Jing Huang7725ccf2009-09-23 17:46:15 -07001919 }
1920
Jing Huang5fbe25c2010-10-18 17:17:23 -07001921 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07001922 * turn off mailbox interrupt by clearing mailbox status
1923 */
Jing Huang53440262010-10-18 17:12:29 -07001924 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1925 readl(ioc->ioc_regs.lpu_mbox_cmd);
Krishna Gudipati11189202011-06-13 15:50:35 -07001926
1927 return BFA_TRUE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001928}
1929
1930void
1931bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m)
1932{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001933 union bfi_ioc_i2h_msg_u *msg;
1934 struct bfa_iocpf_s *iocpf = &ioc->iocpf;
Jing Huang7725ccf2009-09-23 17:46:15 -07001935
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001936 msg = (union bfi_ioc_i2h_msg_u *) m;
Jing Huang7725ccf2009-09-23 17:46:15 -07001937
1938 bfa_ioc_stats(ioc, ioc_isrs);
1939
1940 switch (msg->mh.msg_id) {
1941 case BFI_IOC_I2H_HBEAT:
1942 break;
1943
Jing Huang7725ccf2009-09-23 17:46:15 -07001944 case BFI_IOC_I2H_ENABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001945 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001946 break;
1947
1948 case BFI_IOC_I2H_DISABLE_REPLY:
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001949 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
Jing Huang7725ccf2009-09-23 17:46:15 -07001950 break;
1951
1952 case BFI_IOC_I2H_GETATTR_REPLY:
1953 bfa_ioc_getattr_reply(ioc);
1954 break;
1955
1956 default:
1957 bfa_trc(ioc, msg->mh.msg_id);
Jing Huangd4b671c2010-12-26 21:46:35 -08001958 WARN_ON(1);
Jing Huang7725ccf2009-09-23 17:46:15 -07001959 }
1960}
1961
Jing Huang5fbe25c2010-10-18 17:17:23 -07001962/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001963 * IOC attach time initialization and setup.
1964 *
1965 * @param[in] ioc memory for IOC
1966 * @param[in] bfa driver instance structure
Jing Huang7725ccf2009-09-23 17:46:15 -07001967 */
1968void
1969bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001970 struct bfa_timer_mod_s *timer_mod)
Jing Huang7725ccf2009-09-23 17:46:15 -07001971{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001972 ioc->bfa = bfa;
1973 ioc->cbfn = cbfn;
1974 ioc->timer_mod = timer_mod;
1975 ioc->fcmode = BFA_FALSE;
1976 ioc->pllinit = BFA_FALSE;
Jing Huang7725ccf2009-09-23 17:46:15 -07001977 ioc->dbg_fwsave_once = BFA_TRUE;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001978 ioc->iocpf.ioc = ioc;
Jing Huang7725ccf2009-09-23 17:46:15 -07001979
1980 bfa_ioc_mbox_attach(ioc);
Krishna Gudipatid37779f2011-06-13 15:42:10 -07001981 INIT_LIST_HEAD(&ioc->notify_q);
Jing Huang7725ccf2009-09-23 17:46:15 -07001982
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07001983 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
1984 bfa_fsm_send_event(ioc, IOC_E_RESET);
Jing Huang7725ccf2009-09-23 17:46:15 -07001985}
1986
Jing Huang5fbe25c2010-10-18 17:17:23 -07001987/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001988 * Driver detach time IOC cleanup.
1989 */
1990void
1991bfa_ioc_detach(struct bfa_ioc_s *ioc)
1992{
1993 bfa_fsm_send_event(ioc, IOC_E_DETACH);
1994}
1995
Jing Huang5fbe25c2010-10-18 17:17:23 -07001996/*
Jing Huang7725ccf2009-09-23 17:46:15 -07001997 * Setup IOC PCI properties.
1998 *
1999 * @param[in] pcidev PCI device information for this IOC
2000 */
2001void
2002bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev,
Krishna Gudipatid37779f2011-06-13 15:42:10 -07002003 enum bfi_pcifn_class clscode)
Jing Huang7725ccf2009-09-23 17:46:15 -07002004{
Krishna Gudipatid37779f2011-06-13 15:42:10 -07002005 ioc->clscode = clscode;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002006 ioc->pcidev = *pcidev;
Krishna Gudipati11189202011-06-13 15:50:35 -07002007
2008 /*
2009 * Initialize IOC and device personality
2010 */
2011 ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
2012 ioc->asic_mode = BFI_ASIC_MODE_FC;
2013
2014 switch (pcidev->device_id) {
2015 case BFA_PCI_DEVICE_ID_FC_8G1P:
2016 case BFA_PCI_DEVICE_ID_FC_8G2P:
2017 ioc->asic_gen = BFI_ASIC_GEN_CB;
2018 break;
2019
2020 case BFA_PCI_DEVICE_ID_CT:
2021 ioc->asic_gen = BFI_ASIC_GEN_CT;
2022 ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2023 ioc->asic_mode = BFI_ASIC_MODE_ETH;
2024 break;
2025
2026 case BFA_PCI_DEVICE_ID_CT_FC:
2027 ioc->asic_gen = BFI_ASIC_GEN_CT;
2028 break;
2029
2030 case BFA_PCI_DEVICE_ID_CT2:
2031 ioc->asic_gen = BFI_ASIC_GEN_CT2;
2032 if (clscode == BFI_PCIFN_CLASS_FC)
2033 ioc->asic_mode = BFI_ASIC_MODE_FC16;
2034 else {
2035 ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2036 ioc->asic_mode = BFI_ASIC_MODE_ETH;
2037 }
2038 break;
2039
2040 default:
2041 WARN_ON(1);
2042 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002043
Jing Huang5fbe25c2010-10-18 17:17:23 -07002044 /*
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002045 * Set asic specific interfaces. See bfa_ioc_cb.c and bfa_ioc_ct.c
2046 */
Krishna Gudipati11189202011-06-13 15:50:35 -07002047 if (ioc->asic_gen == BFI_ASIC_GEN_CB)
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002048 bfa_ioc_set_cb_hwif(ioc);
Krishna Gudipati11189202011-06-13 15:50:35 -07002049 else if (ioc->asic_gen == BFI_ASIC_GEN_CT)
2050 bfa_ioc_set_ct_hwif(ioc);
2051 else {
2052 WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
2053 bfa_ioc_set_ct2_hwif(ioc);
2054 bfa_ioc_ct2_poweron(ioc);
2055 }
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002056
Jing Huang7725ccf2009-09-23 17:46:15 -07002057 bfa_ioc_map_port(ioc);
2058 bfa_ioc_reg_init(ioc);
2059}
2060
Jing Huang5fbe25c2010-10-18 17:17:23 -07002061/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002062 * Initialize IOC dma memory
2063 *
2064 * @param[in] dm_kva kernel virtual address of IOC dma memory
2065 * @param[in] dm_pa physical address of IOC dma memory
2066 */
2067void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002068bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa)
Jing Huang7725ccf2009-09-23 17:46:15 -07002069{
Jing Huang5fbe25c2010-10-18 17:17:23 -07002070 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002071 * dma memory for firmware attribute
2072 */
2073 ioc->attr_dma.kva = dm_kva;
2074 ioc->attr_dma.pa = dm_pa;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002075 ioc->attr = (struct bfi_ioc_attr_s *) dm_kva;
Jing Huang7725ccf2009-09-23 17:46:15 -07002076}
2077
Jing Huang7725ccf2009-09-23 17:46:15 -07002078void
2079bfa_ioc_enable(struct bfa_ioc_s *ioc)
2080{
2081 bfa_ioc_stats(ioc, ioc_enables);
2082 ioc->dbg_fwsave_once = BFA_TRUE;
2083
2084 bfa_fsm_send_event(ioc, IOC_E_ENABLE);
2085}
2086
2087void
2088bfa_ioc_disable(struct bfa_ioc_s *ioc)
2089{
2090 bfa_ioc_stats(ioc, ioc_disables);
2091 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
2092}
2093
Jing Huang7725ccf2009-09-23 17:46:15 -07002094
Jing Huang5fbe25c2010-10-18 17:17:23 -07002095/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002096 * Initialize memory for saving firmware trace. Driver must initialize
2097 * trace memory before call bfa_ioc_enable().
2098 */
2099void
2100bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave)
2101{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002102 ioc->dbg_fwsave = dbg_fwsave;
Maggie Zhangf7f73812010-12-09 19:08:43 -08002103 ioc->dbg_fwsave_len = (ioc->iocpf.auto_recover) ? BFA_DBG_FWTRC_LEN : 0;
Jing Huang7725ccf2009-09-23 17:46:15 -07002104}
2105
Jing Huang5fbe25c2010-10-18 17:17:23 -07002106/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002107 * Register mailbox message handler functions
2108 *
2109 * @param[in] ioc IOC instance
2110 * @param[in] mcfuncs message class handler functions
2111 */
2112void
2113bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
2114{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002115 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2116 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002117
2118 for (mc = 0; mc < BFI_MC_MAX; mc++)
2119 mod->mbhdlr[mc].cbfn = mcfuncs[mc];
2120}
2121
Jing Huang5fbe25c2010-10-18 17:17:23 -07002122/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002123 * Register mailbox message handler function, to be called by common modules
2124 */
2125void
2126bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc,
2127 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2128{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002129 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
Jing Huang7725ccf2009-09-23 17:46:15 -07002130
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002131 mod->mbhdlr[mc].cbfn = cbfn;
2132 mod->mbhdlr[mc].cbarg = cbarg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002133}
2134
Jing Huang5fbe25c2010-10-18 17:17:23 -07002135/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002136 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2137 * Responsibility of caller to serialize
2138 *
2139 * @param[in] ioc IOC instance
2140 * @param[i] cmd Mailbox command
2141 */
2142void
2143bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd)
2144{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002145 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2146 u32 stat;
Jing Huang7725ccf2009-09-23 17:46:15 -07002147
Jing Huang5fbe25c2010-10-18 17:17:23 -07002148 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002149 * If a previous command is pending, queue new command
2150 */
2151 if (!list_empty(&mod->cmd_q)) {
2152 list_add_tail(&cmd->qe, &mod->cmd_q);
2153 return;
2154 }
2155
Jing Huang5fbe25c2010-10-18 17:17:23 -07002156 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002157 * If mailbox is busy, queue command for poll timer
2158 */
Jing Huang53440262010-10-18 17:12:29 -07002159 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
Jing Huang7725ccf2009-09-23 17:46:15 -07002160 if (stat) {
2161 list_add_tail(&cmd->qe, &mod->cmd_q);
2162 return;
2163 }
2164
Jing Huang5fbe25c2010-10-18 17:17:23 -07002165 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002166 * mailbox is free -- queue command to firmware
2167 */
2168 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
2169}
2170
Jing Huang5fbe25c2010-10-18 17:17:23 -07002171/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002172 * Handle mailbox interrupts
2173 */
2174void
2175bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc)
2176{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002177 struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod;
2178 struct bfi_mbmsg_s m;
2179 int mc;
Jing Huang7725ccf2009-09-23 17:46:15 -07002180
Krishna Gudipati11189202011-06-13 15:50:35 -07002181 if (!bfa_ioc_msgget(ioc, &m))
2182 return;
Jing Huang7725ccf2009-09-23 17:46:15 -07002183
Jing Huang5fbe25c2010-10-18 17:17:23 -07002184 /*
Jing Huang7725ccf2009-09-23 17:46:15 -07002185 * Treat IOC message class as special.
2186 */
2187 mc = m.mh.msg_class;
2188 if (mc == BFI_MC_IOC) {
2189 bfa_ioc_isr(ioc, &m);
2190 return;
2191 }
2192
2193 if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2194 return;
2195
2196 mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
2197}
2198
2199void
2200bfa_ioc_error_isr(struct bfa_ioc_s *ioc)
2201{
2202 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2203}
2204
Jing Huanged969322010-07-08 19:45:56 -07002205void
2206bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc)
2207{
2208 ioc->fcmode = BFA_TRUE;
Jing Huanged969322010-07-08 19:45:56 -07002209}
2210
Jing Huang5fbe25c2010-10-18 17:17:23 -07002211/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002212 * return true if IOC is disabled
2213 */
2214bfa_boolean_t
2215bfa_ioc_is_disabled(struct bfa_ioc_s *ioc)
2216{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002217 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2218 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
Jing Huang7725ccf2009-09-23 17:46:15 -07002219}
2220
Jing Huang5fbe25c2010-10-18 17:17:23 -07002221/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002222 * return true if IOC firmware is different.
2223 */
2224bfa_boolean_t
2225bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2226{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002227 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
2228 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_fwcheck) ||
2229 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
Jing Huang7725ccf2009-09-23 17:46:15 -07002230}
2231
2232#define bfa_ioc_state_disabled(__sm) \
2233 (((__sm) == BFI_IOC_UNINIT) || \
2234 ((__sm) == BFI_IOC_INITING) || \
2235 ((__sm) == BFI_IOC_HWINIT) || \
2236 ((__sm) == BFI_IOC_DISABLED) || \
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002237 ((__sm) == BFI_IOC_FAIL) || \
Jing Huang7725ccf2009-09-23 17:46:15 -07002238 ((__sm) == BFI_IOC_CFG_DISABLED))
2239
Jing Huang5fbe25c2010-10-18 17:17:23 -07002240/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002241 * Check if adapter is disabled -- both IOCs should be in a disabled
2242 * state.
2243 */
2244bfa_boolean_t
2245bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc)
2246{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002247 u32 ioc_state;
Jing Huang7725ccf2009-09-23 17:46:15 -07002248
2249 if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
2250 return BFA_FALSE;
2251
Krishna Gudipati11189202011-06-13 15:50:35 -07002252 ioc_state = readl(ioc->ioc_regs.ioc_fwstate);
Jing Huang7725ccf2009-09-23 17:46:15 -07002253 if (!bfa_ioc_state_disabled(ioc_state))
2254 return BFA_FALSE;
2255
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002256 if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) {
Krishna Gudipati11189202011-06-13 15:50:35 -07002257 ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002258 if (!bfa_ioc_state_disabled(ioc_state))
2259 return BFA_FALSE;
2260 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002261
2262 return BFA_TRUE;
2263}
2264
Jing Huang8f4bfad2010-12-26 21:50:10 -08002265/*
Krishna Gudipatif1d584d2010-12-13 16:17:11 -08002266 * Reset IOC fwstate registers.
2267 */
2268void
2269bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc)
2270{
2271 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
2272 writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
2273}
2274
Jing Huang7725ccf2009-09-23 17:46:15 -07002275#define BFA_MFG_NAME "Brocade"
2276void
2277bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
2278 struct bfa_adapter_attr_s *ad_attr)
2279{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002280 struct bfi_ioc_attr_s *ioc_attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002281
2282 ioc_attr = ioc->attr;
Jing Huang7725ccf2009-09-23 17:46:15 -07002283
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002284 bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2285 bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2286 bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2287 bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
Jing Huang6a18b162010-10-18 17:08:54 -07002288 memcpy(&ad_attr->vpd, &ioc_attr->vpd,
Jing Huang7725ccf2009-09-23 17:46:15 -07002289 sizeof(struct bfa_mfg_vpd_s));
2290
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002291 ad_attr->nports = bfa_ioc_get_nports(ioc);
2292 ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002293
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002294 bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2295 /* For now, model descr uses same model string */
2296 bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
Jing Huang7725ccf2009-09-23 17:46:15 -07002297
Jing Huanged969322010-07-08 19:45:56 -07002298 ad_attr->card_type = ioc_attr->card_type;
2299 ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2300
Jing Huang7725ccf2009-09-23 17:46:15 -07002301 if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2302 ad_attr->prototype = 1;
2303 else
2304 ad_attr->prototype = 0;
2305
Maggie Zhangf7f73812010-12-09 19:08:43 -08002306 ad_attr->pwwn = ioc->attr->pwwn;
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002307 ad_attr->mac = bfa_ioc_get_mac(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002308
2309 ad_attr->pcie_gen = ioc_attr->pcie_gen;
2310 ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2311 ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2312 ad_attr->asic_rev = ioc_attr->asic_rev;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002313
2314 bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
Jing Huang7725ccf2009-09-23 17:46:15 -07002315
Krishna Gudipati11189202011-06-13 15:50:35 -07002316 ad_attr->cna_capable = bfa_ioc_is_cna(ioc);
2317 ad_attr->trunk_capable = (ad_attr->nports > 1) &&
2318 !bfa_ioc_is_cna(ioc) && !ad_attr->is_mezz;
Jing Huang7725ccf2009-09-23 17:46:15 -07002319}
2320
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002321enum bfa_ioc_type_e
2322bfa_ioc_get_type(struct bfa_ioc_s *ioc)
2323{
Krishna Gudipati11189202011-06-13 15:50:35 -07002324 enum bfi_port_mode mode;
2325
2326 if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002327 return BFA_IOC_TYPE_LL;
Krishna Gudipati11189202011-06-13 15:50:35 -07002328
2329 WARN_ON(ioc->clscode != BFI_PCIFN_CLASS_FC);
2330
2331 mode = (ioc->port_id == 0) ? ioc->port0_mode : ioc->port1_mode;
2332 return (mode == BFI_PORT_MODE_FC)
2333 ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002334}
2335
Jing Huang7725ccf2009-09-23 17:46:15 -07002336void
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002337bfa_ioc_get_adapter_serial_num(struct bfa_ioc_s *ioc, char *serial_num)
2338{
Jing Huang6a18b162010-10-18 17:08:54 -07002339 memset((void *)serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2340 memcpy((void *)serial_num,
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002341 (void *)ioc->attr->brcd_serialnum,
2342 BFA_ADAPTER_SERIAL_NUM_LEN);
2343}
2344
2345void
2346bfa_ioc_get_adapter_fw_ver(struct bfa_ioc_s *ioc, char *fw_ver)
2347{
Jing Huang6a18b162010-10-18 17:08:54 -07002348 memset((void *)fw_ver, 0, BFA_VERSION_LEN);
2349 memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002350}
2351
2352void
2353bfa_ioc_get_pci_chip_rev(struct bfa_ioc_s *ioc, char *chip_rev)
2354{
Jing Huangd4b671c2010-12-26 21:46:35 -08002355 WARN_ON(!chip_rev);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002356
Jing Huang6a18b162010-10-18 17:08:54 -07002357 memset((void *)chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002358
2359 chip_rev[0] = 'R';
2360 chip_rev[1] = 'e';
2361 chip_rev[2] = 'v';
2362 chip_rev[3] = '-';
2363 chip_rev[4] = ioc->attr->asic_rev;
2364 chip_rev[5] = '\0';
2365}
2366
2367void
2368bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc_s *ioc, char *optrom_ver)
2369{
Jing Huang6a18b162010-10-18 17:08:54 -07002370 memset((void *)optrom_ver, 0, BFA_VERSION_LEN);
2371 memcpy(optrom_ver, ioc->attr->optrom_version,
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002372 BFA_VERSION_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002373}
2374
2375void
2376bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer)
2377{
Jing Huang6a18b162010-10-18 17:08:54 -07002378 memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2379 memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002380}
2381
2382void
2383bfa_ioc_get_adapter_model(struct bfa_ioc_s *ioc, char *model)
2384{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002385 struct bfi_ioc_attr_s *ioc_attr;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002386
Jing Huangd4b671c2010-12-26 21:46:35 -08002387 WARN_ON(!model);
Jing Huang6a18b162010-10-18 17:08:54 -07002388 memset((void *)model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002389
2390 ioc_attr = ioc->attr;
2391
Jing Huang5fbe25c2010-10-18 17:17:23 -07002392 /*
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002393 * model name
2394 */
Jing Huang6a18b162010-10-18 17:08:54 -07002395 snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002396 BFA_MFG_NAME, ioc_attr->card_type);
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002397}
2398
2399enum bfa_ioc_state
2400bfa_ioc_get_state(struct bfa_ioc_s *ioc)
2401{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002402 enum bfa_iocpf_state iocpf_st;
2403 enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2404
2405 if (ioc_st == BFA_IOC_ENABLING ||
2406 ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2407
2408 iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2409
2410 switch (iocpf_st) {
2411 case BFA_IOCPF_SEMWAIT:
2412 ioc_st = BFA_IOC_SEMWAIT;
2413 break;
2414
2415 case BFA_IOCPF_HWINIT:
2416 ioc_st = BFA_IOC_HWINIT;
2417 break;
2418
2419 case BFA_IOCPF_FWMISMATCH:
2420 ioc_st = BFA_IOC_FWMISMATCH;
2421 break;
2422
2423 case BFA_IOCPF_FAIL:
2424 ioc_st = BFA_IOC_FAIL;
2425 break;
2426
2427 case BFA_IOCPF_INITFAIL:
2428 ioc_st = BFA_IOC_INITFAIL;
2429 break;
2430
2431 default:
2432 break;
2433 }
2434 }
2435
2436 return ioc_st;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002437}
2438
2439void
Jing Huang7725ccf2009-09-23 17:46:15 -07002440bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr)
2441{
Jing Huang6a18b162010-10-18 17:08:54 -07002442 memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s));
Jing Huang7725ccf2009-09-23 17:46:15 -07002443
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002444 ioc_attr->state = bfa_ioc_get_state(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002445 ioc_attr->port_id = ioc->port_id;
2446
Krishna Gudipati2993cc72010-03-05 19:36:47 -08002447 ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002448
2449 bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2450
2451 ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2452 ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
Krishna Gudipati0a4b1fc2010-03-05 19:37:57 -08002453 bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
Jing Huang7725ccf2009-09-23 17:46:15 -07002454}
2455
Jing Huang7725ccf2009-09-23 17:46:15 -07002456mac_t
2457bfa_ioc_get_mac(struct bfa_ioc_s *ioc)
2458{
Jing Huang15b64a82010-07-08 19:48:12 -07002459 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002460 * Check the IOC type and return the appropriate MAC
Jing Huang15b64a82010-07-08 19:48:12 -07002461 */
2462 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002463 return ioc->attr->fcoe_mac;
Jing Huang15b64a82010-07-08 19:48:12 -07002464 else
2465 return ioc->attr->mac;
2466}
2467
Jing Huang15b64a82010-07-08 19:48:12 -07002468mac_t
2469bfa_ioc_get_mfg_mac(struct bfa_ioc_s *ioc)
2470{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002471 mac_t m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002472
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002473 m = ioc->attr->mfg_mac;
2474 if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
2475 m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
2476 else
2477 bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
2478 bfa_ioc_pcifn(ioc));
Jing Huang7725ccf2009-09-23 17:46:15 -07002479
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002480 return m;
Jing Huang7725ccf2009-09-23 17:46:15 -07002481}
2482
Jing Huang7725ccf2009-09-23 17:46:15 -07002483bfa_boolean_t
2484bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc)
2485{
Krishna Gudipati11189202011-06-13 15:50:35 -07002486 return ioc->fcmode || bfa_asic_id_cb(ioc->pcidev.device_id);
Jing Huang7725ccf2009-09-23 17:46:15 -07002487}
2488
Jing Huang5fbe25c2010-10-18 17:17:23 -07002489/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002490 * Retrieve saved firmware trace from a prior IOC failure.
2491 */
2492bfa_status_t
2493bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2494{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002495 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002496
2497 if (ioc->dbg_fwsave_len == 0)
2498 return BFA_STATUS_ENOFSAVE;
2499
2500 tlen = *trclen;
2501 if (tlen > ioc->dbg_fwsave_len)
2502 tlen = ioc->dbg_fwsave_len;
2503
Jing Huang6a18b162010-10-18 17:08:54 -07002504 memcpy(trcdata, ioc->dbg_fwsave, tlen);
Jing Huang7725ccf2009-09-23 17:46:15 -07002505 *trclen = tlen;
2506 return BFA_STATUS_OK;
2507}
2508
Krishna Gudipati738c9e62010-03-05 19:36:19 -08002509
Jing Huang5fbe25c2010-10-18 17:17:23 -07002510/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002511 * Retrieve saved firmware trace from a prior IOC failure.
2512 */
2513bfa_status_t
2514bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen)
2515{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002516 u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc));
2517 int tlen;
2518 bfa_status_t status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002519
2520 bfa_trc(ioc, *trclen);
2521
Jing Huang7725ccf2009-09-23 17:46:15 -07002522 tlen = *trclen;
2523 if (tlen > BFA_DBG_FWTRC_LEN)
2524 tlen = BFA_DBG_FWTRC_LEN;
Jing Huang7725ccf2009-09-23 17:46:15 -07002525
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002526 status = bfa_ioc_smem_read(ioc, trcdata, loff, tlen);
2527 *trclen = tlen;
2528 return status;
2529}
Jing Huang7725ccf2009-09-23 17:46:15 -07002530
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002531static void
2532bfa_ioc_send_fwsync(struct bfa_ioc_s *ioc)
2533{
2534 struct bfa_mbox_cmd_s cmd;
2535 struct bfi_ioc_ctrl_req_s *req = (struct bfi_ioc_ctrl_req_s *) cmd.msg;
Jing Huang7725ccf2009-09-23 17:46:15 -07002536
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002537 bfi_h2i_set(req->mh, BFI_MC_IOC, BFI_IOC_H2I_DBG_SYNC,
2538 bfa_ioc_portid(ioc));
Krishna Gudipatid37779f2011-06-13 15:42:10 -07002539 req->clscode = cpu_to_be16(ioc->clscode);
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002540 bfa_ioc_mbox_queue(ioc, &cmd);
2541}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002542
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002543static void
2544bfa_ioc_fwsync(struct bfa_ioc_s *ioc)
2545{
2546 u32 fwsync_iter = 1000;
2547
2548 bfa_ioc_send_fwsync(ioc);
2549
Jing Huang5fbe25c2010-10-18 17:17:23 -07002550 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002551 * After sending a fw sync mbox command wait for it to
2552 * take effect. We will not wait for a response because
2553 * 1. fw_sync mbox cmd doesn't have a response.
2554 * 2. Even if we implement that, interrupts might not
2555 * be enabled when we call this function.
2556 * So, just keep checking if any mbox cmd is pending, and
2557 * after waiting for a reasonable amount of time, go ahead.
2558 * It is possible that fw has crashed and the mbox command
2559 * is never acknowledged.
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002560 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002561 while (bfa_ioc_mbox_cmd_pending(ioc) && fwsync_iter > 0)
2562 fwsync_iter--;
2563}
Krishna Gudipati0a20de42010-03-05 19:34:20 -08002564
Jing Huang5fbe25c2010-10-18 17:17:23 -07002565/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002566 * Dump firmware smem
2567 */
2568bfa_status_t
2569bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
2570 u32 *offset, int *buflen)
2571{
2572 u32 loff;
2573 int dlen;
2574 bfa_status_t status;
2575 u32 smem_len = BFA_IOC_FW_SMEM_SIZE(ioc);
Jing Huang7725ccf2009-09-23 17:46:15 -07002576
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002577 if (*offset >= smem_len) {
2578 *offset = *buflen = 0;
2579 return BFA_STATUS_EINVAL;
2580 }
2581
2582 loff = *offset;
2583 dlen = *buflen;
2584
Jing Huang5fbe25c2010-10-18 17:17:23 -07002585 /*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002586 * First smem read, sync smem before proceeding
2587 * No need to sync before reading every chunk.
2588 */
2589 if (loff == 0)
2590 bfa_ioc_fwsync(ioc);
2591
2592 if ((loff + dlen) >= smem_len)
2593 dlen = smem_len - loff;
2594
2595 status = bfa_ioc_smem_read(ioc, buf, loff, dlen);
2596
2597 if (status != BFA_STATUS_OK) {
2598 *offset = *buflen = 0;
2599 return status;
2600 }
2601
2602 *offset += dlen;
2603
2604 if (*offset >= smem_len)
2605 *offset = 0;
2606
2607 *buflen = dlen;
2608
2609 return status;
2610}
2611
Jing Huang5fbe25c2010-10-18 17:17:23 -07002612/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002613 * Firmware statistics
2614 */
2615bfa_status_t
2616bfa_ioc_fw_stats_get(struct bfa_ioc_s *ioc, void *stats)
2617{
2618 u32 loff = BFI_IOC_FWSTATS_OFF + \
2619 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2620 int tlen;
2621 bfa_status_t status;
2622
2623 if (ioc->stats_busy) {
2624 bfa_trc(ioc, ioc->stats_busy);
2625 return BFA_STATUS_DEVBUSY;
2626 }
2627 ioc->stats_busy = BFA_TRUE;
2628
2629 tlen = sizeof(struct bfa_fw_stats_s);
2630 status = bfa_ioc_smem_read(ioc, stats, loff, tlen);
2631
2632 ioc->stats_busy = BFA_FALSE;
2633 return status;
2634}
2635
2636bfa_status_t
2637bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
2638{
2639 u32 loff = BFI_IOC_FWSTATS_OFF + \
2640 BFI_IOC_FWSTATS_SZ * (bfa_ioc_portid(ioc));
2641 int tlen;
2642 bfa_status_t status;
2643
2644 if (ioc->stats_busy) {
2645 bfa_trc(ioc, ioc->stats_busy);
2646 return BFA_STATUS_DEVBUSY;
2647 }
2648 ioc->stats_busy = BFA_TRUE;
2649
2650 tlen = sizeof(struct bfa_fw_stats_s);
2651 status = bfa_ioc_smem_clr(ioc, loff, tlen);
2652
2653 ioc->stats_busy = BFA_FALSE;
2654 return status;
Jing Huang7725ccf2009-09-23 17:46:15 -07002655}
2656
Jing Huang5fbe25c2010-10-18 17:17:23 -07002657/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002658 * Save firmware trace if configured.
2659 */
2660static void
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08002661bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -07002662{
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002663 int tlen;
Jing Huang7725ccf2009-09-23 17:46:15 -07002664
Krishna Gudipati4e78efe2010-12-13 16:16:09 -08002665 if (ioc->dbg_fwsave_once) {
2666 ioc->dbg_fwsave_once = BFA_FALSE;
2667 if (ioc->dbg_fwsave_len) {
2668 tlen = ioc->dbg_fwsave_len;
2669 bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
2670 }
Jing Huang7725ccf2009-09-23 17:46:15 -07002671 }
2672}
2673
Jing Huang5fbe25c2010-10-18 17:17:23 -07002674/*
Jing Huang7725ccf2009-09-23 17:46:15 -07002675 * Firmware failure detected. Start recovery actions.
2676 */
2677static void
2678bfa_ioc_recover(struct bfa_ioc_s *ioc)
2679{
Jing Huang7725ccf2009-09-23 17:46:15 -07002680 bfa_ioc_stats(ioc, ioc_hbfails);
2681 bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
2682}
2683
Jing Huang7725ccf2009-09-23 17:46:15 -07002684static void
Jing Huang07b28382010-07-08 19:59:24 -07002685bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc)
Jing Huang7725ccf2009-09-23 17:46:15 -07002686{
Jing Huang07b28382010-07-08 19:59:24 -07002687 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
2688 return;
Jing Huang7725ccf2009-09-23 17:46:15 -07002689}
2690
Jing Huang5fbe25c2010-10-18 17:17:23 -07002691/*
Maggie Zhangdf0f1932010-12-09 19:07:46 -08002692 * BFA IOC PF private functions
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002693 */
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002694static void
2695bfa_iocpf_timeout(void *ioc_arg)
2696{
2697 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2698
2699 bfa_trc(ioc, 0);
2700 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
2701}
2702
2703static void
2704bfa_iocpf_sem_timeout(void *ioc_arg)
2705{
2706 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2707
2708 bfa_ioc_hw_sem_get(ioc);
2709}
2710
Krishna Gudipati775c7742011-06-13 15:52:12 -07002711static void
2712bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc)
2713{
2714 u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
2715
2716 bfa_trc(ioc, fwstate);
2717
2718 if (fwstate == BFI_IOC_DISABLED) {
2719 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
2720 return;
2721 }
2722
2723 if (ioc->iocpf.poll_time >= BFA_IOC_TOV)
2724 bfa_iocpf_timeout(ioc);
2725 else {
2726 ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
2727 bfa_iocpf_poll_timer_start(ioc);
2728 }
2729}
2730
2731static void
2732bfa_iocpf_poll_timeout(void *ioc_arg)
2733{
2734 struct bfa_ioc_s *ioc = (struct bfa_ioc_s *) ioc_arg;
2735
2736 bfa_ioc_poll_fwinit(ioc);
2737}
2738
Jing Huang5fbe25c2010-10-18 17:17:23 -07002739/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002740 * bfa timer function
2741 */
2742void
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002743bfa_timer_beat(struct bfa_timer_mod_s *mod)
2744{
2745 struct list_head *qh = &mod->timer_q;
2746 struct list_head *qe, *qe_next;
2747 struct bfa_timer_s *elem;
2748 struct list_head timedout_q;
2749
2750 INIT_LIST_HEAD(&timedout_q);
2751
2752 qe = bfa_q_next(qh);
2753
2754 while (qe != qh) {
2755 qe_next = bfa_q_next(qe);
2756
2757 elem = (struct bfa_timer_s *) qe;
2758 if (elem->timeout <= BFA_TIMER_FREQ) {
2759 elem->timeout = 0;
2760 list_del(&elem->qe);
2761 list_add_tail(&elem->qe, &timedout_q);
2762 } else {
2763 elem->timeout -= BFA_TIMER_FREQ;
2764 }
2765
2766 qe = qe_next; /* go to next elem */
2767 }
2768
2769 /*
2770 * Pop all the timeout entries
2771 */
2772 while (!list_empty(&timedout_q)) {
2773 bfa_q_deq(&timedout_q, &elem);
2774 elem->timercb(elem->arg);
2775 }
2776}
2777
Jing Huang5fbe25c2010-10-18 17:17:23 -07002778/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002779 * Should be called with lock protection
2780 */
2781void
2782bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer,
2783 void (*timercb) (void *), void *arg, unsigned int timeout)
2784{
2785
Jing Huangd4b671c2010-12-26 21:46:35 -08002786 WARN_ON(timercb == NULL);
2787 WARN_ON(bfa_q_is_on_q(&mod->timer_q, timer));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002788
2789 timer->timeout = timeout;
2790 timer->timercb = timercb;
2791 timer->arg = arg;
2792
2793 list_add_tail(&timer->qe, &mod->timer_q);
2794}
2795
Jing Huang5fbe25c2010-10-18 17:17:23 -07002796/*
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002797 * Should be called with lock protection
2798 */
2799void
2800bfa_timer_stop(struct bfa_timer_s *timer)
2801{
Jing Huangd4b671c2010-12-26 21:46:35 -08002802 WARN_ON(list_empty(&timer->qe));
Krishna Gudipatia36c61f2010-09-15 11:50:55 -07002803
2804 list_del(&timer->qe);
2805}