blob: 7a3e79c7834b1245a721d95733ae12c17ba9e141 [file] [log] [blame]
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001/*
2 * Linux network driver for Brocade Converged Network Adapter.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License (GPL) Version 2 as
6 * published by the Free Software Foundation
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 */
13/*
14 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
15 * All rights reserved
16 * www.brocade.com
17 */
18
19#include "bfa_ioc.h"
Rasesh Modya9602492011-08-02 12:36:06 +000020#include "bfi_reg.h"
Rasesh Mody8b230ed2010-08-23 20:24:12 -070021#include "bfa_defs.h"
22
23/**
24 * IOC local definitions
25 */
26
Rasesh Mody8b230ed2010-08-23 20:24:12 -070027/**
28 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
29 */
30
31#define bfa_ioc_firmware_lock(__ioc) \
32 ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
33#define bfa_ioc_firmware_unlock(__ioc) \
34 ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
35#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
36#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
Rasesh Mody1d32f762010-12-23 21:45:09 +000037#define bfa_ioc_notify_fail(__ioc) \
38 ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
Rasesh Mody79ea6c82011-04-14 08:05:18 +000039#define bfa_ioc_sync_start(__ioc) \
40 ((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
Rasesh Mody1d32f762010-12-23 21:45:09 +000041#define bfa_ioc_sync_join(__ioc) \
42 ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
43#define bfa_ioc_sync_leave(__ioc) \
44 ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc))
45#define bfa_ioc_sync_ack(__ioc) \
46 ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc))
47#define bfa_ioc_sync_complete(__ioc) \
48 ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc))
Rasesh Mody8b230ed2010-08-23 20:24:12 -070049
Rasesh Mody8b230ed2010-08-23 20:24:12 -070050#define bfa_ioc_mbox_cmd_pending(__ioc) \
51 (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
52 readl((__ioc)->ioc_regs.hfn_mbox_cmd))
53
Rasesh Modyb7ee31c52010-10-05 15:46:05 +000054static bool bfa_nw_auto_recover = true;
Rasesh Mody8b230ed2010-08-23 20:24:12 -070055
56/*
57 * forward declarations
58 */
Rasesh Modyd4e16d42011-07-22 08:07:47 +000059static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -070060static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
61static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
62static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
Rasesh Mody078086f2011-08-08 16:21:39 +000063static void bfa_ioc_poll_fwinit(struct bfa_ioc *ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -070064static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
65static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
66static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
67static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
68static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
69static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
70static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
Rasesh Modyfdad4002011-07-22 08:07:45 +000071static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -070072static void bfa_ioc_recover(struct bfa_ioc *ioc);
73static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
Rasesh Modybd5a92e2011-07-22 08:07:42 +000074static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -070075static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
76static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
Krishna Gudipati7afc5db2011-12-22 13:30:19 +000077static void bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +000078static void bfa_ioc_fail_notify(struct bfa_ioc *ioc);
79static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc);
80static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +000081static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
Rasesh Mody078086f2011-08-08 16:21:39 +000082static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +000083static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
Rasesh Mody8a891422010-08-25 23:00:27 -070084static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type,
85 u32 boot_param);
86static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
Rasesh Mody8a891422010-08-25 23:00:27 -070087static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
88 char *serial_num);
89static void bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc,
90 char *fw_ver);
91static void bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc,
92 char *chip_rev);
93static void bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc,
94 char *optrom_ver);
95static void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc,
96 char *manufacturer);
97static void bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model);
98static u64 bfa_ioc_get_pwwn(struct bfa_ioc *ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -070099
100/**
Rasesh Mody1d32f762010-12-23 21:45:09 +0000101 * IOC state machine definitions/declarations
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700102 */
103enum ioc_event {
Rasesh Mody1d32f762010-12-23 21:45:09 +0000104 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 */
Rasesh Mody078086f2011-08-08 16:21:39 +0000111 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 */
115 IOC_E_HWFAILED = 12, /*!< PCI mapping failure notice */
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700116};
117
Rasesh Mody1d32f762010-12-23 21:45:09 +0000118bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700119bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700120bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
121bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
122bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000123bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event);
124bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700125bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
126bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
Rasesh Mody078086f2011-08-08 16:21:39 +0000127bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700128
129static struct bfa_sm_table ioc_sm_table[] = {
Rasesh Mody1d32f762010-12-23 21:45:09 +0000130 {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT},
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700131 {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
Rasesh Mody1d32f762010-12-23 21:45:09 +0000132 {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700133 {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
134 {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
Rasesh Mody1d32f762010-12-23 21:45:09 +0000135 {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
136 {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700137 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
138 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
Rasesh Mody078086f2011-08-08 16:21:39 +0000139 {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL},
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700140};
141
Rasesh Mody1d32f762010-12-23 21:45:09 +0000142/*
143 * Forward declareations for iocpf state machine
144 */
145static void bfa_iocpf_enable(struct bfa_ioc *ioc);
146static void bfa_iocpf_disable(struct bfa_ioc *ioc);
147static void bfa_iocpf_fail(struct bfa_ioc *ioc);
148static void bfa_iocpf_initfail(struct bfa_ioc *ioc);
149static void bfa_iocpf_getattrfail(struct bfa_ioc *ioc);
150static void bfa_iocpf_stop(struct bfa_ioc *ioc);
151
152/**
153 * IOCPF state machine events
154 */
155enum iocpf_event {
156 IOCPF_E_ENABLE = 1, /*!< IOCPF enable request */
157 IOCPF_E_DISABLE = 2, /*!< IOCPF disable request */
158 IOCPF_E_STOP = 3, /*!< stop on driver detach */
Rasesh Mody0120b992011-07-22 08:07:41 +0000159 IOCPF_E_FWREADY = 4, /*!< f/w initialization done */
Rasesh Mody1d32f762010-12-23 21:45:09 +0000160 IOCPF_E_FWRSP_ENABLE = 5, /*!< enable f/w response */
161 IOCPF_E_FWRSP_DISABLE = 6, /*!< disable f/w response */
162 IOCPF_E_FAIL = 7, /*!< failure notice by ioc sm */
163 IOCPF_E_INITFAIL = 8, /*!< init fail notice by ioc sm */
164 IOCPF_E_GETATTRFAIL = 9, /*!< init fail notice by ioc sm */
165 IOCPF_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */
166 IOCPF_E_TIMEOUT = 11, /*!< f/w response timeout */
Rasesh Mody078086f2011-08-08 16:21:39 +0000167 IOCPF_E_SEM_ERROR = 12, /*!< h/w sem mapping error */
Rasesh Mody1d32f762010-12-23 21:45:09 +0000168};
169
170/**
171 * IOCPF states
172 */
173enum bfa_iocpf_state {
174 BFA_IOCPF_RESET = 1, /*!< IOC is in reset state */
175 BFA_IOCPF_SEMWAIT = 2, /*!< Waiting for IOC h/w semaphore */
176 BFA_IOCPF_HWINIT = 3, /*!< IOC h/w is being initialized */
177 BFA_IOCPF_READY = 4, /*!< IOCPF is initialized */
178 BFA_IOCPF_INITFAIL = 5, /*!< IOCPF failed */
179 BFA_IOCPF_FAIL = 6, /*!< IOCPF failed */
180 BFA_IOCPF_DISABLING = 7, /*!< IOCPF is being disabled */
181 BFA_IOCPF_DISABLED = 8, /*!< IOCPF is disabled */
182 BFA_IOCPF_FWMISMATCH = 9, /*!< IOC f/w different from drivers */
183};
184
185bfa_fsm_state_decl(bfa_iocpf, reset, struct bfa_iocpf, enum iocpf_event);
186bfa_fsm_state_decl(bfa_iocpf, fwcheck, struct bfa_iocpf, enum iocpf_event);
187bfa_fsm_state_decl(bfa_iocpf, mismatch, struct bfa_iocpf, enum iocpf_event);
188bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf, enum iocpf_event);
189bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf, enum iocpf_event);
190bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf, enum iocpf_event);
191bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf, enum iocpf_event);
192bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf,
193 enum iocpf_event);
194bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf, enum iocpf_event);
195bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf, enum iocpf_event);
196bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf, enum iocpf_event);
197bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf, enum iocpf_event);
198bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf,
199 enum iocpf_event);
200bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf, enum iocpf_event);
201
202static struct bfa_sm_table iocpf_sm_table[] = {
203 {BFA_SM(bfa_iocpf_sm_reset), BFA_IOCPF_RESET},
204 {BFA_SM(bfa_iocpf_sm_fwcheck), BFA_IOCPF_FWMISMATCH},
205 {BFA_SM(bfa_iocpf_sm_mismatch), BFA_IOCPF_FWMISMATCH},
206 {BFA_SM(bfa_iocpf_sm_semwait), BFA_IOCPF_SEMWAIT},
207 {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT},
208 {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT},
209 {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY},
210 {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL},
211 {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL},
212 {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL},
213 {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL},
214 {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING},
215 {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING},
216 {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED},
217};
218
219/**
220 * IOC State Machine
221 */
222
223/**
224 * Beginning state. IOC uninit state.
225 */
226static void
227bfa_ioc_sm_uninit_entry(struct bfa_ioc *ioc)
228{
229}
230
231/**
232 * IOC is in uninit state.
233 */
234static void
235bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event)
236{
237 switch (event) {
238 case IOC_E_RESET:
239 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
240 break;
241
242 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000243 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000244 }
245}
246
247/**
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700248 * Reset entry actions -- initialize state machine
249 */
250static void
251bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
252{
Rasesh Mody1d32f762010-12-23 21:45:09 +0000253 bfa_fsm_set_state(&ioc->iocpf, bfa_iocpf_sm_reset);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700254}
255
256/**
Rasesh Mody1d32f762010-12-23 21:45:09 +0000257 * IOC is in reset state.
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700258 */
259static void
260bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
261{
262 switch (event) {
263 case IOC_E_ENABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000264 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700265 break;
266
267 case IOC_E_DISABLE:
268 bfa_ioc_disable_comp(ioc);
269 break;
270
271 case IOC_E_DETACH:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000272 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
273 break;
274
275 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000276 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000277 }
278}
279
280static void
281bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
282{
283 bfa_iocpf_enable(ioc);
284}
285
286/**
287 * Host IOC function is being enabled, awaiting response from firmware.
288 * Semaphore is acquired.
289 */
290static void
291bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
292{
293 switch (event) {
294 case IOC_E_ENABLED:
295 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
296 break;
297
Rasesh Modyf374b362011-07-22 08:07:46 +0000298 case IOC_E_PFFAILED:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000299 /* !!! fall through !!! */
300 case IOC_E_HWERROR:
301 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Rasesh Mody078086f2011-08-08 16:21:39 +0000302 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Rasesh Modyf374b362011-07-22 08:07:46 +0000303 if (event != IOC_E_PFFAILED)
Rasesh Mody1d32f762010-12-23 21:45:09 +0000304 bfa_iocpf_initfail(ioc);
305 break;
306
Rasesh Mody078086f2011-08-08 16:21:39 +0000307 case IOC_E_HWFAILED:
308 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
309 bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
310 break;
311
Rasesh Mody1d32f762010-12-23 21:45:09 +0000312 case IOC_E_DISABLE:
313 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
314 break;
315
316 case IOC_E_DETACH:
317 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
318 bfa_iocpf_stop(ioc);
319 break;
320
321 case IOC_E_ENABLE:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700322 break;
323
324 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000325 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700326 }
327}
328
329/**
330 * Semaphore should be acquired for version check.
331 */
332static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700333bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
334{
Rasesh Mody1d32f762010-12-23 21:45:09 +0000335 mod_timer(&ioc->ioc_timer, jiffies +
336 msecs_to_jiffies(BFA_IOC_TOV));
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700337 bfa_ioc_send_getattr(ioc);
338}
339
340/**
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700341 * IOC configuration in progress. Timer is active.
342 */
343static void
344bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
345{
346 switch (event) {
347 case IOC_E_FWRSP_GETATTR:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000348 del_timer(&ioc->ioc_timer);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700349 bfa_ioc_check_attr_wwns(ioc);
Rasesh Mody078086f2011-08-08 16:21:39 +0000350 bfa_ioc_hb_monitor(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700351 bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
352 break;
353
Rasesh Modyf374b362011-07-22 08:07:46 +0000354 case IOC_E_PFFAILED:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700355 case IOC_E_HWERROR:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000356 del_timer(&ioc->ioc_timer);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700357 /* fall through */
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700358 case IOC_E_TIMEOUT:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000359 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Rasesh Mody078086f2011-08-08 16:21:39 +0000360 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Rasesh Modyf374b362011-07-22 08:07:46 +0000361 if (event != IOC_E_PFFAILED)
Rasesh Mody1d32f762010-12-23 21:45:09 +0000362 bfa_iocpf_getattrfail(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700363 break;
364
365 case IOC_E_DISABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000366 del_timer(&ioc->ioc_timer);
367 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
368 break;
369
370 case IOC_E_ENABLE:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700371 break;
372
373 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000374 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700375 }
376}
377
378static void
379bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
380{
381 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
Rasesh Mody078086f2011-08-08 16:21:39 +0000382 bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700383}
384
385static void
386bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
387{
388 switch (event) {
389 case IOC_E_ENABLE:
390 break;
391
392 case IOC_E_DISABLE:
393 bfa_ioc_hb_stop(ioc);
394 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
395 break;
396
Rasesh Modyf374b362011-07-22 08:07:46 +0000397 case IOC_E_PFFAILED:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700398 case IOC_E_HWERROR:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700399 bfa_ioc_hb_stop(ioc);
400 /* !!! fall through !!! */
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700401 case IOC_E_HBFAIL:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000402 if (ioc->iocpf.auto_recover)
403 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
404 else
405 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
406
Rasesh Mody078086f2011-08-08 16:21:39 +0000407 bfa_ioc_fail_notify(ioc);
408
Rasesh Modyf374b362011-07-22 08:07:46 +0000409 if (event != IOC_E_PFFAILED)
Rasesh Mody1d32f762010-12-23 21:45:09 +0000410 bfa_iocpf_fail(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700411 break;
412
413 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000414 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700415 }
416}
417
418static void
419bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
420{
Rasesh Mody1d32f762010-12-23 21:45:09 +0000421 bfa_iocpf_disable(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700422}
423
424/**
Rasesh Modyaafd5c22011-09-27 10:39:09 +0000425 * IOC is being disabled
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700426 */
427static void
428bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
429{
430 switch (event) {
Rasesh Mody1d32f762010-12-23 21:45:09 +0000431 case IOC_E_DISABLED:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700432 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
433 break;
434
435 case IOC_E_HWERROR:
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700436 /*
Rasesh Mody1d32f762010-12-23 21:45:09 +0000437 * No state change. Will move to disabled state
438 * after iocpf sm completes failure processing and
439 * moves to disabled state.
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700440 */
Rasesh Mody1d32f762010-12-23 21:45:09 +0000441 bfa_iocpf_fail(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700442 break;
443
Rasesh Mody078086f2011-08-08 16:21:39 +0000444 case IOC_E_HWFAILED:
445 bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
446 bfa_ioc_disable_comp(ioc);
447 break;
448
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700449 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000450 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700451 }
452}
453
454/**
Rasesh Modyaafd5c22011-09-27 10:39:09 +0000455 * IOC disable completion entry.
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700456 */
457static void
458bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
459{
460 bfa_ioc_disable_comp(ioc);
461}
462
463static void
464bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
465{
466 switch (event) {
467 case IOC_E_ENABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000468 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700469 break;
470
471 case IOC_E_DISABLE:
472 ioc->cbfn->disable_cbfn(ioc->bfa);
473 break;
474
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700475 case IOC_E_DETACH:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000476 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
477 bfa_iocpf_stop(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700478 break;
479
480 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000481 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700482 }
483}
484
485static void
Rasesh Mody1d32f762010-12-23 21:45:09 +0000486bfa_ioc_sm_fail_retry_entry(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700487{
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700488}
489
490/**
Rasesh Mody1d32f762010-12-23 21:45:09 +0000491 * Hardware initialization retry.
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700492 */
493static void
Rasesh Mody1d32f762010-12-23 21:45:09 +0000494bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event)
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700495{
496 switch (event) {
Rasesh Mody1d32f762010-12-23 21:45:09 +0000497 case IOC_E_ENABLED:
498 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
499 break;
500
Rasesh Modyf374b362011-07-22 08:07:46 +0000501 case IOC_E_PFFAILED:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000502 case IOC_E_HWERROR:
503 /**
504 * Initialization retry failed.
505 */
506 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
Rasesh Mody078086f2011-08-08 16:21:39 +0000507 bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
Rasesh Modyf374b362011-07-22 08:07:46 +0000508 if (event != IOC_E_PFFAILED)
Rasesh Mody1d32f762010-12-23 21:45:09 +0000509 bfa_iocpf_initfail(ioc);
510 break;
511
Rasesh Mody078086f2011-08-08 16:21:39 +0000512 case IOC_E_HWFAILED:
513 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
514 bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000515 break;
516
517 case IOC_E_ENABLE:
518 break;
519
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700520 case IOC_E_DISABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000521 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700522 break;
523
524 case IOC_E_DETACH:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000525 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
526 bfa_iocpf_stop(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700527 break;
528
529 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000530 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700531 }
532}
533
534static void
Rasesh Mody1d32f762010-12-23 21:45:09 +0000535bfa_ioc_sm_fail_entry(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700536{
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700537}
538
539/**
Rasesh Mody1d32f762010-12-23 21:45:09 +0000540 * IOC failure.
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700541 */
542static void
Rasesh Mody1d32f762010-12-23 21:45:09 +0000543bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event)
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700544{
545 switch (event) {
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700546 case IOC_E_ENABLE:
547 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
548 break;
549
550 case IOC_E_DISABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000551 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700552 break;
553
Rasesh Mody1d32f762010-12-23 21:45:09 +0000554 case IOC_E_DETACH:
555 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
556 bfa_iocpf_stop(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700557 break;
558
559 case IOC_E_HWERROR:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000560 /* HB failure notification, ignore. */
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700561 break;
Rasesh Mody1d32f762010-12-23 21:45:09 +0000562
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700563 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000564 bfa_sm_fault(event);
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700565 }
566}
567
Rasesh Mody078086f2011-08-08 16:21:39 +0000568static void
569bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc)
570{
571}
572
573/**
574 * IOC failure.
575 */
576static void
577bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event)
578{
579 switch (event) {
580
581 case IOC_E_ENABLE:
582 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
583 break;
584
585 case IOC_E_DISABLE:
586 ioc->cbfn->disable_cbfn(ioc->bfa);
587 break;
588
589 case IOC_E_DETACH:
590 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
591 break;
592
593 default:
594 bfa_sm_fault(event);
595 }
596}
597
Rasesh Mody8b230ed2010-08-23 20:24:12 -0700598/**
Rasesh Mody1d32f762010-12-23 21:45:09 +0000599 * IOCPF State Machine
600 */
601
602/**
603 * Reset entry actions -- initialize state machine
604 */
605static void
606bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf)
607{
Rasesh Mody078086f2011-08-08 16:21:39 +0000608 iocpf->fw_mismatch_notified = false;
Rasesh Mody1d32f762010-12-23 21:45:09 +0000609 iocpf->auto_recover = bfa_nw_auto_recover;
610}
611
612/**
613 * Beginning state. IOC is in reset state.
614 */
615static void
616bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event 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:
Rasesh Modyac51f602011-07-22 08:07:43 +0000627 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000628 }
629}
630
631/**
632 * Semaphore should be acquired for version check.
633 */
634static void
635bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf)
636{
Rasesh Modyd4e16d42011-07-22 08:07:47 +0000637 bfa_ioc_hw_sem_init(iocpf->ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000638 bfa_ioc_hw_sem_get(iocpf->ioc);
639}
640
641/**
642 * Awaiting h/w semaphore to continue with version check.
643 */
644static void
645bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
646{
647 struct bfa_ioc *ioc = iocpf->ioc;
648
649 switch (event) {
650 case IOCPF_E_SEMLOCKED:
651 if (bfa_ioc_firmware_lock(ioc)) {
Rasesh Mody79ea6c82011-04-14 08:05:18 +0000652 if (bfa_ioc_sync_start(ioc)) {
Rasesh Mody1d32f762010-12-23 21:45:09 +0000653 bfa_ioc_sync_join(ioc);
654 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
655 } else {
656 bfa_ioc_firmware_unlock(ioc);
657 bfa_nw_ioc_hw_sem_release(ioc);
658 mod_timer(&ioc->sem_timer, jiffies +
659 msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
660 }
661 } else {
662 bfa_nw_ioc_hw_sem_release(ioc);
663 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch);
664 }
665 break;
666
Rasesh Mody078086f2011-08-08 16:21:39 +0000667 case IOCPF_E_SEM_ERROR:
668 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
669 bfa_ioc_pf_hwfailed(ioc);
670 break;
671
Rasesh Mody1d32f762010-12-23 21:45:09 +0000672 case IOCPF_E_DISABLE:
673 bfa_ioc_hw_sem_get_cancel(ioc);
674 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
675 bfa_ioc_pf_disabled(ioc);
676 break;
677
678 case IOCPF_E_STOP:
679 bfa_ioc_hw_sem_get_cancel(ioc);
680 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
681 break;
682
683 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000684 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000685 }
686}
687
688/**
689 * Notify enable completion callback
690 */
691static void
692bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf)
693{
694 /* Call only the first time sm enters fwmismatch state. */
Joe Perches23677ce2012-02-09 11:17:23 +0000695 if (!iocpf->fw_mismatch_notified)
Rasesh Mody1d32f762010-12-23 21:45:09 +0000696 bfa_ioc_pf_fwmismatch(iocpf->ioc);
697
Rasesh Mody078086f2011-08-08 16:21:39 +0000698 iocpf->fw_mismatch_notified = true;
Rasesh Mody1d32f762010-12-23 21:45:09 +0000699 mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
700 msecs_to_jiffies(BFA_IOC_TOV));
701}
702
703/**
704 * Awaiting firmware version match.
705 */
706static void
707bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event)
708{
709 struct bfa_ioc *ioc = iocpf->ioc;
710
711 switch (event) {
712 case IOCPF_E_TIMEOUT:
713 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fwcheck);
714 break;
715
716 case IOCPF_E_DISABLE:
717 del_timer(&ioc->iocpf_timer);
718 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
719 bfa_ioc_pf_disabled(ioc);
720 break;
721
722 case IOCPF_E_STOP:
723 del_timer(&ioc->iocpf_timer);
724 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
725 break;
726
727 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000728 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000729 }
730}
731
732/**
733 * Request for semaphore.
734 */
735static void
736bfa_iocpf_sm_semwait_entry(struct bfa_iocpf *iocpf)
737{
738 bfa_ioc_hw_sem_get(iocpf->ioc);
739}
740
741/**
742 * Awaiting semaphore for h/w initialzation.
743 */
744static void
745bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event)
746{
747 struct bfa_ioc *ioc = iocpf->ioc;
748
749 switch (event) {
750 case IOCPF_E_SEMLOCKED:
751 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 bfa_nw_ioc_hw_sem_release(ioc);
756 mod_timer(&ioc->sem_timer, jiffies +
757 msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
758 }
759 break;
760
Rasesh Mody078086f2011-08-08 16:21:39 +0000761 case IOCPF_E_SEM_ERROR:
762 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
763 bfa_ioc_pf_hwfailed(ioc);
764 break;
765
Rasesh Mody1d32f762010-12-23 21:45:09 +0000766 case IOCPF_E_DISABLE:
767 bfa_ioc_hw_sem_get_cancel(ioc);
768 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
769 break;
770
771 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000772 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000773 }
774}
775
776static void
777bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf)
778{
Rasesh Mody078086f2011-08-08 16:21:39 +0000779 iocpf->poll_time = 0;
Rasesh Modyaafd5c22011-09-27 10:39:09 +0000780 bfa_ioc_reset(iocpf->ioc, false);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000781}
782
783/**
784 * Hardware is being initialized. Interrupts are enabled.
785 * Holding hardware semaphore lock.
786 */
787static void
788bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event)
789{
790 struct bfa_ioc *ioc = iocpf->ioc;
791
792 switch (event) {
793 case IOCPF_E_FWREADY:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000794 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling);
795 break;
796
Rasesh Mody1d32f762010-12-23 21:45:09 +0000797 case IOCPF_E_TIMEOUT:
798 bfa_nw_ioc_hw_sem_release(ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000799 bfa_ioc_pf_failed(ioc);
800 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
801 break;
802
803 case IOCPF_E_DISABLE:
804 del_timer(&ioc->iocpf_timer);
805 bfa_ioc_sync_leave(ioc);
806 bfa_nw_ioc_hw_sem_release(ioc);
807 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
808 break;
809
810 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000811 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000812 }
813}
814
815static void
816bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf)
817{
818 mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
819 msecs_to_jiffies(BFA_IOC_TOV));
Rasesh Mody078086f2011-08-08 16:21:39 +0000820 /**
821 * Enable Interrupts before sending fw IOC ENABLE cmd.
822 */
823 iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000824 bfa_ioc_send_enable(iocpf->ioc);
825}
826
827/**
828 * Host IOC function is being enabled, awaiting response from firmware.
829 * Semaphore is acquired.
830 */
831static void
832bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
833{
834 struct bfa_ioc *ioc = iocpf->ioc;
835
836 switch (event) {
837 case IOCPF_E_FWRSP_ENABLE:
838 del_timer(&ioc->iocpf_timer);
839 bfa_nw_ioc_hw_sem_release(ioc);
840 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_ready);
841 break;
842
843 case IOCPF_E_INITFAIL:
844 del_timer(&ioc->iocpf_timer);
845 /*
846 * !!! fall through !!!
847 */
848 case IOCPF_E_TIMEOUT:
849 bfa_nw_ioc_hw_sem_release(ioc);
850 if (event == IOCPF_E_TIMEOUT)
851 bfa_ioc_pf_failed(ioc);
852 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
853 break;
854
855 case IOCPF_E_DISABLE:
856 del_timer(&ioc->iocpf_timer);
857 bfa_nw_ioc_hw_sem_release(ioc);
858 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
859 break;
860
Rasesh Mody1d32f762010-12-23 21:45:09 +0000861 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000862 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000863 }
864}
865
Rasesh Mody1d32f762010-12-23 21:45:09 +0000866static void
867bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf)
868{
869 bfa_ioc_pf_enabled(iocpf->ioc);
870}
871
872static void
873bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event)
874{
Rasesh Mody1d32f762010-12-23 21:45:09 +0000875 switch (event) {
876 case IOCPF_E_DISABLE:
877 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling);
878 break;
879
880 case IOCPF_E_GETATTRFAIL:
881 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync);
882 break;
883
884 case IOCPF_E_FAIL:
885 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync);
886 break;
887
Rasesh Mody1d32f762010-12-23 21:45:09 +0000888 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000889 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000890 }
891}
892
893static void
894bfa_iocpf_sm_disabling_entry(struct bfa_iocpf *iocpf)
895{
896 mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies +
897 msecs_to_jiffies(BFA_IOC_TOV));
898 bfa_ioc_send_disable(iocpf->ioc);
899}
900
901/**
902 * IOC is being disabled
903 */
904static void
905bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event)
906{
907 struct bfa_ioc *ioc = iocpf->ioc;
908
909 switch (event) {
910 case IOCPF_E_FWRSP_DISABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000911 del_timer(&ioc->iocpf_timer);
912 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
913 break;
914
915 case IOCPF_E_FAIL:
916 del_timer(&ioc->iocpf_timer);
917 /*
918 * !!! fall through !!!
919 */
920
921 case IOCPF_E_TIMEOUT:
922 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
923 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
924 break;
925
926 case IOCPF_E_FWRSP_ENABLE:
927 break;
928
929 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000930 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000931 }
932}
933
934static void
935bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf *iocpf)
936{
937 bfa_ioc_hw_sem_get(iocpf->ioc);
938}
939
940/**
941 * IOC hb ack request is being removed.
942 */
943static void
944bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
945{
946 struct bfa_ioc *ioc = iocpf->ioc;
947
948 switch (event) {
949 case IOCPF_E_SEMLOCKED:
950 bfa_ioc_sync_leave(ioc);
951 bfa_nw_ioc_hw_sem_release(ioc);
952 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
953 break;
954
Rasesh Mody078086f2011-08-08 16:21:39 +0000955 case IOCPF_E_SEM_ERROR:
956 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
957 bfa_ioc_pf_hwfailed(ioc);
958 break;
959
Rasesh Mody1d32f762010-12-23 21:45:09 +0000960 case IOCPF_E_FAIL:
961 break;
962
963 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000964 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000965 }
966}
967
968/**
969 * IOC disable completion entry.
970 */
971static void
972bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf)
973{
Rasesh Modyfdad4002011-07-22 08:07:45 +0000974 bfa_ioc_mbox_flush(iocpf->ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000975 bfa_ioc_pf_disabled(iocpf->ioc);
976}
977
978static void
979bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event)
980{
981 struct bfa_ioc *ioc = iocpf->ioc;
982
983 switch (event) {
984 case IOCPF_E_ENABLE:
Rasesh Mody1d32f762010-12-23 21:45:09 +0000985 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
986 break;
987
988 case IOCPF_E_STOP:
989 bfa_ioc_firmware_unlock(ioc);
990 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
991 break;
992
993 default:
Rasesh Modyac51f602011-07-22 08:07:43 +0000994 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +0000995 }
996}
997
998static void
999bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf *iocpf)
1000{
Krishna Gudipati7afc5db2011-12-22 13:30:19 +00001001 bfa_nw_ioc_debug_save_ftrc(iocpf->ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001002 bfa_ioc_hw_sem_get(iocpf->ioc);
1003}
1004
1005/**
1006 * Hardware initialization failed.
1007 */
1008static void
1009bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
1010{
1011 struct bfa_ioc *ioc = iocpf->ioc;
1012
1013 switch (event) {
1014 case IOCPF_E_SEMLOCKED:
1015 bfa_ioc_notify_fail(ioc);
Rasesh Mody078086f2011-08-08 16:21:39 +00001016 bfa_ioc_sync_leave(ioc);
1017 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
1018 bfa_nw_ioc_hw_sem_release(ioc);
1019 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
1020 break;
1021
1022 case IOCPF_E_SEM_ERROR:
1023 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1024 bfa_ioc_pf_hwfailed(ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001025 break;
1026
1027 case IOCPF_E_DISABLE:
1028 bfa_ioc_hw_sem_get_cancel(ioc);
1029 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1030 break;
1031
1032 case IOCPF_E_STOP:
1033 bfa_ioc_hw_sem_get_cancel(ioc);
1034 bfa_ioc_firmware_unlock(ioc);
1035 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1036 break;
1037
1038 case IOCPF_E_FAIL:
1039 break;
1040
1041 default:
Rasesh Modyac51f602011-07-22 08:07:43 +00001042 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001043 }
1044}
1045
1046static void
1047bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf)
1048{
Rasesh Mody1d32f762010-12-23 21:45:09 +00001049}
1050
1051/**
1052 * Hardware initialization failed.
1053 */
1054static void
1055bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event)
1056{
1057 struct bfa_ioc *ioc = iocpf->ioc;
1058
1059 switch (event) {
1060 case IOCPF_E_DISABLE:
1061 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1062 break;
1063
1064 case IOCPF_E_STOP:
1065 bfa_ioc_firmware_unlock(ioc);
1066 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset);
1067 break;
1068
1069 default:
Rasesh Modyac51f602011-07-22 08:07:43 +00001070 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001071 }
1072}
1073
1074static void
1075bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf)
1076{
1077 /**
1078 * Mark IOC as failed in hardware and stop firmware.
1079 */
1080 bfa_ioc_lpu_stop(iocpf->ioc);
1081
1082 /**
1083 * Flush any queued up mailbox requests.
1084 */
Rasesh Modyfdad4002011-07-22 08:07:45 +00001085 bfa_ioc_mbox_flush(iocpf->ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001086 bfa_ioc_hw_sem_get(iocpf->ioc);
1087}
1088
1089/**
1090 * IOC is in failed state.
1091 */
1092static void
1093bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event)
1094{
1095 struct bfa_ioc *ioc = iocpf->ioc;
1096
1097 switch (event) {
1098 case IOCPF_E_SEMLOCKED:
Rasesh Mody1d32f762010-12-23 21:45:09 +00001099 bfa_ioc_sync_ack(ioc);
1100 bfa_ioc_notify_fail(ioc);
1101 if (!iocpf->auto_recover) {
1102 bfa_ioc_sync_leave(ioc);
Rasesh Mody078086f2011-08-08 16:21:39 +00001103 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001104 bfa_nw_ioc_hw_sem_release(ioc);
1105 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1106 } else {
1107 if (bfa_ioc_sync_complete(ioc))
1108 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
1109 else {
1110 bfa_nw_ioc_hw_sem_release(ioc);
1111 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait);
1112 }
1113 }
1114 break;
1115
Rasesh Mody078086f2011-08-08 16:21:39 +00001116 case IOCPF_E_SEM_ERROR:
1117 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail);
1118 bfa_ioc_pf_hwfailed(ioc);
1119 break;
1120
Rasesh Mody1d32f762010-12-23 21:45:09 +00001121 case IOCPF_E_DISABLE:
1122 bfa_ioc_hw_sem_get_cancel(ioc);
1123 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync);
1124 break;
1125
1126 case IOCPF_E_FAIL:
1127 break;
1128
1129 default:
Rasesh Modyac51f602011-07-22 08:07:43 +00001130 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001131 }
1132}
1133
1134static void
1135bfa_iocpf_sm_fail_entry(struct bfa_iocpf *iocpf)
1136{
1137}
1138
1139/**
1140 * @brief
1141 * IOC is in failed state.
1142 */
1143static void
1144bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event)
1145{
1146 switch (event) {
1147 case IOCPF_E_DISABLE:
1148 bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled);
1149 break;
1150
1151 default:
Rasesh Modyac51f602011-07-22 08:07:43 +00001152 bfa_sm_fault(event);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001153 }
1154}
1155
1156/**
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001157 * BFA IOC private functions
1158 */
1159
Rasesh Modybd5a92e2011-07-22 08:07:42 +00001160/**
1161 * Notify common modules registered for notification.
1162 */
1163static void
1164bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event)
1165{
1166 struct bfa_ioc_notify *notify;
1167 struct list_head *qe;
1168
1169 list_for_each(qe, &ioc->notify_q) {
1170 notify = (struct bfa_ioc_notify *)qe;
1171 notify->cbfn(notify->cbarg, event);
1172 }
1173}
1174
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001175static void
1176bfa_ioc_disable_comp(struct bfa_ioc *ioc)
1177{
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001178 ioc->cbfn->disable_cbfn(ioc->bfa);
Rasesh Modybd5a92e2011-07-22 08:07:42 +00001179 bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001180}
1181
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001182bool
Rasesh Mody8a891422010-08-25 23:00:27 -07001183bfa_nw_ioc_sem_get(void __iomem *sem_reg)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001184{
1185 u32 r32;
1186 int cnt = 0;
1187#define BFA_SEM_SPINCNT 3000
1188
1189 r32 = readl(sem_reg);
1190
Rasesh Mody078086f2011-08-08 16:21:39 +00001191 while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) {
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001192 cnt++;
1193 udelay(2);
1194 r32 = readl(sem_reg);
1195 }
1196
Rasesh Mody078086f2011-08-08 16:21:39 +00001197 if (!(r32 & 1))
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001198 return true;
1199
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001200 return false;
1201}
1202
1203void
Rasesh Mody8a891422010-08-25 23:00:27 -07001204bfa_nw_ioc_sem_release(void __iomem *sem_reg)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001205{
Rasesh Mody1d51a132011-09-16 15:06:46 +00001206 readl(sem_reg);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001207 writel(1, sem_reg);
1208}
1209
Jing Huange491c772012-04-04 05:42:08 +00001210/* Clear fwver hdr */
1211static void
1212bfa_ioc_fwver_clear(struct bfa_ioc *ioc)
1213{
1214 u32 pgnum, pgoff, loff = 0;
1215 int i;
1216
1217 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1218 pgoff = PSS_SMEM_PGOFF(loff);
1219 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1220
1221 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32)); i++) {
1222 writel(0, ioc->ioc_regs.smem_page_start + loff);
1223 loff += sizeof(u32);
1224 }
1225}
1226
1227
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001228static void
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001229bfa_ioc_hw_sem_init(struct bfa_ioc *ioc)
1230{
1231 struct bfi_ioc_image_hdr fwhdr;
Jing Huange491c772012-04-04 05:42:08 +00001232 u32 fwstate, r32;
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001233
Jing Huange491c772012-04-04 05:42:08 +00001234 /* Spin on init semaphore to serialize. */
1235 r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);
1236 while (r32 & 0x1) {
1237 udelay(20);
1238 r32 = readl(ioc->ioc_regs.ioc_init_sem_reg);
1239 }
1240
1241 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
1242 if (fwstate == BFI_IOC_UNINIT) {
1243 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001244 return;
Jing Huange491c772012-04-04 05:42:08 +00001245 }
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001246
1247 bfa_nw_ioc_fwver_get(ioc, &fwhdr);
1248
Jing Huange491c772012-04-04 05:42:08 +00001249 if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) {
1250 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001251 return;
Jing Huange491c772012-04-04 05:42:08 +00001252 }
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001253
Jing Huange491c772012-04-04 05:42:08 +00001254 bfa_ioc_fwver_clear(ioc);
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001255 writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
Jing Huange491c772012-04-04 05:42:08 +00001256 writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001257
1258 /*
1259 * Try to lock and then unlock the semaphore.
1260 */
1261 readl(ioc->ioc_regs.ioc_sem_reg);
1262 writel(1, ioc->ioc_regs.ioc_sem_reg);
Jing Huange491c772012-04-04 05:42:08 +00001263
1264 /* Unlock init semaphore */
1265 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
Rasesh Modyd4e16d42011-07-22 08:07:47 +00001266}
1267
1268static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001269bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
1270{
1271 u32 r32;
1272
1273 /**
1274 * First read to the semaphore register will return 0, subsequent reads
1275 * will return 1. Semaphore is released by writing 1 to the register
1276 */
1277 r32 = readl(ioc->ioc_regs.ioc_sem_reg);
Rasesh Mody078086f2011-08-08 16:21:39 +00001278 if (r32 == ~0) {
1279 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR);
1280 return;
1281 }
1282 if (!(r32 & 1)) {
Rasesh Mody1d32f762010-12-23 21:45:09 +00001283 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001284 return;
1285 }
1286
1287 mod_timer(&ioc->sem_timer, jiffies +
1288 msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
1289}
1290
1291void
Rasesh Mody8a891422010-08-25 23:00:27 -07001292bfa_nw_ioc_hw_sem_release(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001293{
1294 writel(1, ioc->ioc_regs.ioc_sem_reg);
1295}
1296
1297static void
1298bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc)
1299{
1300 del_timer(&ioc->sem_timer);
1301}
1302
1303/**
1304 * @brief
1305 * Initialize LPU local memory (aka secondary memory / SRAM)
1306 */
1307static void
1308bfa_ioc_lmem_init(struct bfa_ioc *ioc)
1309{
1310 u32 pss_ctl;
1311 int i;
1312#define PSS_LMEM_INIT_TIME 10000
1313
1314 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1315 pss_ctl &= ~__PSS_LMEM_RESET;
1316 pss_ctl |= __PSS_LMEM_INIT_EN;
1317
1318 /*
1319 * i2c workaround 12.5khz clock
1320 */
1321 pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
1322 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1323
1324 /**
1325 * wait for memory initialization to be complete
1326 */
1327 i = 0;
1328 do {
1329 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1330 i++;
1331 } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
1332
1333 /**
1334 * If memory initialization is not successful, IOC timeout will catch
1335 * such failures.
1336 */
1337 BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
1338
1339 pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
1340 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1341}
1342
1343static void
1344bfa_ioc_lpu_start(struct bfa_ioc *ioc)
1345{
1346 u32 pss_ctl;
1347
1348 /**
1349 * Take processor out of reset.
1350 */
1351 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1352 pss_ctl &= ~__PSS_LPU0_RESET;
1353
1354 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1355}
1356
1357static void
1358bfa_ioc_lpu_stop(struct bfa_ioc *ioc)
1359{
1360 u32 pss_ctl;
1361
1362 /**
1363 * Put processors in reset.
1364 */
1365 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
1366 pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
1367
1368 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
1369}
1370
1371/**
1372 * Get driver and firmware versions.
1373 */
1374void
Rasesh Mody8a891422010-08-25 23:00:27 -07001375bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001376{
David S. Miller58598542011-04-17 16:51:36 -07001377 u32 pgnum;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001378 u32 loff = 0;
1379 int i;
1380 u32 *fwsig = (u32 *) fwhdr;
1381
1382 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001383 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1384
1385 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));
1386 i++) {
1387 fwsig[i] =
1388 swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
1389 loff += sizeof(u32);
1390 }
1391}
1392
1393/**
1394 * Returns TRUE if same.
1395 */
1396bool
Rasesh Mody8a891422010-08-25 23:00:27 -07001397bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001398{
1399 struct bfi_ioc_image_hdr *drv_fwhdr;
1400 int i;
1401
1402 drv_fwhdr = (struct bfi_ioc_image_hdr *)
Rasesh Mody078086f2011-08-08 16:21:39 +00001403 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001404
1405 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1406 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
1407 return false;
1408 }
1409
1410 return true;
1411}
1412
1413/**
1414 * Return true if current running version is valid. Firmware signature and
1415 * execution context (driver/bios) must match.
1416 */
1417static bool
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001418bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001419{
1420 struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
1421
Rasesh Mody8a891422010-08-25 23:00:27 -07001422 bfa_nw_ioc_fwver_get(ioc, &fwhdr);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001423 drv_fwhdr = (struct bfi_ioc_image_hdr *)
Rasesh Mody078086f2011-08-08 16:21:39 +00001424 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001425
1426 if (fwhdr.signature != drv_fwhdr->signature)
1427 return false;
1428
Rasesh Mody078086f2011-08-08 16:21:39 +00001429 if (swab32(fwhdr.bootenv) != boot_env)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001430 return false;
1431
Rasesh Mody8a891422010-08-25 23:00:27 -07001432 return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001433}
1434
1435/**
1436 * Conditionally flush any pending message from firmware at start.
1437 */
1438static void
1439bfa_ioc_msgflush(struct bfa_ioc *ioc)
1440{
1441 u32 r32;
1442
1443 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
1444 if (r32)
1445 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1446}
1447
1448/**
1449 * @img ioc_init_logic.jpg
1450 */
1451static void
1452bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
1453{
1454 enum bfi_ioc_state ioc_fwstate;
1455 bool fwvalid;
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001456 u32 boot_env;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001457
1458 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
1459
1460 if (force)
1461 ioc_fwstate = BFI_IOC_UNINIT;
1462
Rasesh Mody078086f2011-08-08 16:21:39 +00001463 boot_env = BFI_FWBOOT_ENV_OS;
1464
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001465 /**
1466 * check if firmware is valid
1467 */
1468 fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001469 false : bfa_ioc_fwver_valid(ioc, boot_env);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001470
1471 if (!fwvalid) {
Rasesh Mody078086f2011-08-08 16:21:39 +00001472 bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
1473 bfa_ioc_poll_fwinit(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001474 return;
1475 }
1476
1477 /**
1478 * If hardware initialization is in progress (initialized by other IOC),
1479 * just wait for an initialization completion interrupt.
1480 */
1481 if (ioc_fwstate == BFI_IOC_INITING) {
Rasesh Mody078086f2011-08-08 16:21:39 +00001482 bfa_ioc_poll_fwinit(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001483 return;
1484 }
1485
1486 /**
1487 * If IOC function is disabled and firmware version is same,
1488 * just re-enable IOC.
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001489 */
Rasesh Mody2c7d3822010-12-23 21:45:06 +00001490 if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) {
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001491 /**
1492 * When using MSI-X any pending firmware ready event should
1493 * be flushed. Otherwise MSI-X interrupts are not delivered.
1494 */
1495 bfa_ioc_msgflush(ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001496 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001497 return;
1498 }
1499
1500 /**
1501 * Initialize the h/w for any other states.
1502 */
Rasesh Mody078086f2011-08-08 16:21:39 +00001503 bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env);
1504 bfa_ioc_poll_fwinit(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001505}
1506
1507void
Rasesh Mody8a891422010-08-25 23:00:27 -07001508bfa_nw_ioc_timeout(void *ioc_arg)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001509{
1510 struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
1511
1512 bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
1513}
1514
Rasesh Mody8a891422010-08-25 23:00:27 -07001515static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001516bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len)
1517{
1518 u32 *msgp = (u32 *) ioc_msg;
1519 u32 i;
1520
1521 BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX));
1522
1523 /*
1524 * first write msg to mailbox registers
1525 */
1526 for (i = 0; i < len / sizeof(u32); i++)
1527 writel(cpu_to_le32(msgp[i]),
1528 ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
1529
1530 for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
1531 writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
1532
1533 /*
1534 * write 1 to mailbox CMD to trigger LPU event
1535 */
1536 writel(1, ioc->ioc_regs.hfn_mbox_cmd);
1537 (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
1538}
1539
1540static void
1541bfa_ioc_send_enable(struct bfa_ioc *ioc)
1542{
1543 struct bfi_ioc_ctrl_req enable_req;
1544 struct timeval tv;
1545
1546 bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
1547 bfa_ioc_portid(ioc));
Rasesh Mody078086f2011-08-08 16:21:39 +00001548 enable_req.clscode = htons(ioc->clscode);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001549 do_gettimeofday(&tv);
1550 enable_req.tv_sec = ntohl(tv.tv_sec);
1551 bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
1552}
1553
1554static void
1555bfa_ioc_send_disable(struct bfa_ioc *ioc)
1556{
1557 struct bfi_ioc_ctrl_req disable_req;
1558
1559 bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
1560 bfa_ioc_portid(ioc));
1561 bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req));
1562}
1563
1564static void
1565bfa_ioc_send_getattr(struct bfa_ioc *ioc)
1566{
1567 struct bfi_ioc_getattr_req attr_req;
1568
1569 bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1570 bfa_ioc_portid(ioc));
1571 bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1572 bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1573}
1574
1575void
Rasesh Mody8a891422010-08-25 23:00:27 -07001576bfa_nw_ioc_hb_check(void *cbarg)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001577{
1578 struct bfa_ioc *ioc = cbarg;
1579 u32 hb_count;
1580
1581 hb_count = readl(ioc->ioc_regs.heartbeat);
1582 if (ioc->hb_count == hb_count) {
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001583 bfa_ioc_recover(ioc);
1584 return;
1585 } else {
1586 ioc->hb_count = hb_count;
1587 }
1588
1589 bfa_ioc_mbox_poll(ioc);
1590 mod_timer(&ioc->hb_timer, jiffies +
1591 msecs_to_jiffies(BFA_IOC_HB_TOV));
1592}
1593
1594static void
1595bfa_ioc_hb_monitor(struct bfa_ioc *ioc)
1596{
1597 ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
1598 mod_timer(&ioc->hb_timer, jiffies +
1599 msecs_to_jiffies(BFA_IOC_HB_TOV));
1600}
1601
1602static void
1603bfa_ioc_hb_stop(struct bfa_ioc *ioc)
1604{
1605 del_timer(&ioc->hb_timer);
1606}
1607
1608/**
1609 * @brief
1610 * Initiate a full firmware download.
1611 */
1612static void
1613bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001614 u32 boot_env)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001615{
1616 u32 *fwimg;
David S. Miller58598542011-04-17 16:51:36 -07001617 u32 pgnum;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001618 u32 loff = 0;
1619 u32 chunkno = 0;
1620 u32 i;
Rasesh Mody078086f2011-08-08 16:21:39 +00001621 u32 asicmode;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001622
Rasesh Mody078086f2011-08-08 16:21:39 +00001623 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001624
1625 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001626
1627 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1628
Rasesh Mody078086f2011-08-08 16:21:39 +00001629 for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) {
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001630 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1631 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
Rasesh Mody078086f2011-08-08 16:21:39 +00001632 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001633 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
1634 }
1635
1636 /**
1637 * write smem
1638 */
1639 writel((swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])),
1640 ((ioc->ioc_regs.smem_page_start) + (loff)));
1641
1642 loff += sizeof(u32);
1643
1644 /**
1645 * handle page offset wrap around
1646 */
1647 loff = PSS_SMEM_PGOFF(loff);
1648 if (loff == 0) {
1649 pgnum++;
1650 writel(pgnum,
1651 ioc->ioc_regs.host_page_num_fn);
1652 }
1653 }
1654
1655 writel(bfa_ioc_smem_pgnum(ioc, 0),
1656 ioc->ioc_regs.host_page_num_fn);
1657
1658 /*
Rasesh Mody078086f2011-08-08 16:21:39 +00001659 * Set boot type, env and device mode at the end.
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001660 */
Rasesh Mody078086f2011-08-08 16:21:39 +00001661 asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
1662 ioc->port0_mode, ioc->port1_mode);
1663 writel(asicmode, ((ioc->ioc_regs.smem_page_start)
1664 + BFI_FWBOOT_DEVMODE_OFF));
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001665 writel(boot_type, ((ioc->ioc_regs.smem_page_start)
Rasesh Mody078086f2011-08-08 16:21:39 +00001666 + (BFI_FWBOOT_TYPE_OFF)));
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001667 writel(boot_env, ((ioc->ioc_regs.smem_page_start)
Rasesh Mody078086f2011-08-08 16:21:39 +00001668 + (BFI_FWBOOT_ENV_OFF)));
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001669}
1670
1671static void
1672bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
1673{
1674 bfa_ioc_hwinit(ioc, force);
1675}
1676
1677/**
Rasesh Mody078086f2011-08-08 16:21:39 +00001678 * BFA ioc enable reply by firmware
1679 */
1680static void
1681bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode,
1682 u8 cap_bm)
1683{
1684 struct bfa_iocpf *iocpf = &ioc->iocpf;
1685
1686 ioc->port_mode = ioc->port_mode_cfg = port_mode;
1687 ioc->ad_cap_bm = cap_bm;
1688 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE);
1689}
1690
1691/**
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001692 * @brief
1693 * Update BFA configuration from firmware configuration.
1694 */
1695static void
1696bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
1697{
1698 struct bfi_ioc_attr *attr = ioc->attr;
1699
1700 attr->adapter_prop = ntohl(attr->adapter_prop);
1701 attr->card_type = ntohl(attr->card_type);
1702 attr->maxfrsize = ntohs(attr->maxfrsize);
1703
1704 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1705}
1706
1707/**
1708 * Attach time initialization of mbox logic.
1709 */
1710static void
1711bfa_ioc_mbox_attach(struct bfa_ioc *ioc)
1712{
1713 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1714 int mc;
1715
1716 INIT_LIST_HEAD(&mod->cmd_q);
1717 for (mc = 0; mc < BFI_MC_MAX; mc++) {
1718 mod->mbhdlr[mc].cbfn = NULL;
1719 mod->mbhdlr[mc].cbarg = ioc->bfa;
1720 }
1721}
1722
1723/**
1724 * Mbox poll timer -- restarts any pending mailbox requests.
1725 */
1726static void
1727bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
1728{
1729 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1730 struct bfa_mbox_cmd *cmd;
Rasesh Mody078086f2011-08-08 16:21:39 +00001731 bfa_mbox_cmd_cbfn_t cbfn;
1732 void *cbarg;
1733 u32 stat;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001734
1735 /**
1736 * If no command pending, do nothing
1737 */
1738 if (list_empty(&mod->cmd_q))
1739 return;
1740
1741 /**
1742 * If previous command is not yet fetched by firmware, do nothing
1743 */
1744 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
1745 if (stat)
1746 return;
1747
1748 /**
1749 * Enqueue command to firmware.
1750 */
1751 bfa_q_deq(&mod->cmd_q, &cmd);
1752 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
Rasesh Mody078086f2011-08-08 16:21:39 +00001753
1754 /**
1755 * Give a callback to the client, indicating that the command is sent
1756 */
1757 if (cmd->cbfn) {
1758 cbfn = cmd->cbfn;
1759 cbarg = cmd->cbarg;
1760 cmd->cbfn = NULL;
1761 cbfn(cbarg);
1762 }
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001763}
1764
1765/**
1766 * Cleanup any pending requests.
1767 */
1768static void
Rasesh Modyfdad4002011-07-22 08:07:45 +00001769bfa_ioc_mbox_flush(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001770{
1771 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1772 struct bfa_mbox_cmd *cmd;
1773
1774 while (!list_empty(&mod->cmd_q))
1775 bfa_q_deq(&mod->cmd_q, &cmd);
1776}
1777
Krishna Gudipati7afc5db2011-12-22 13:30:19 +00001778/**
1779 * Read data from SMEM to host through PCI memmap
1780 *
1781 * @param[in] ioc memory for IOC
1782 * @param[in] tbuf app memory to store data from smem
1783 * @param[in] soff smem offset
1784 * @param[in] sz size of smem in bytes
1785 */
1786static int
1787bfa_nw_ioc_smem_read(struct bfa_ioc *ioc, void *tbuf, u32 soff, u32 sz)
1788{
1789 u32 pgnum, loff, r32;
1790 int i, len;
1791 u32 *buf = tbuf;
1792
1793 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, soff);
1794 loff = PSS_SMEM_PGOFF(soff);
1795
1796 /*
1797 * Hold semaphore to serialize pll init and fwtrc.
1798 */
1799 if (bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg) == 0)
1800 return 1;
1801
1802 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1803
1804 len = sz/sizeof(u32);
1805 for (i = 0; i < len; i++) {
1806 r32 = swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
1807 buf[i] = be32_to_cpu(r32);
1808 loff += sizeof(u32);
1809
1810 /**
1811 * handle page offset wrap around
1812 */
1813 loff = PSS_SMEM_PGOFF(loff);
1814 if (loff == 0) {
1815 pgnum++;
1816 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1817 }
1818 }
1819
1820 writel(PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, 0),
1821 ioc->ioc_regs.host_page_num_fn);
1822
1823 /*
1824 * release semaphore
1825 */
1826 readl(ioc->ioc_regs.ioc_init_sem_reg);
1827 writel(1, ioc->ioc_regs.ioc_init_sem_reg);
1828 return 0;
1829}
1830
1831/**
1832 * Retrieve saved firmware trace from a prior IOC failure.
1833 */
1834int
1835bfa_nw_ioc_debug_fwtrc(struct bfa_ioc *ioc, void *trcdata, int *trclen)
1836{
1837 u32 loff = BFI_IOC_TRC_OFF + BNA_DBG_FWTRC_LEN * ioc->port_id;
1838 int tlen, status = 0;
1839
1840 tlen = *trclen;
1841 if (tlen > BNA_DBG_FWTRC_LEN)
1842 tlen = BNA_DBG_FWTRC_LEN;
1843
1844 status = bfa_nw_ioc_smem_read(ioc, trcdata, loff, tlen);
1845 *trclen = tlen;
1846 return status;
1847}
1848
1849/**
1850 * Save firmware trace if configured.
1851 */
1852static void
1853bfa_nw_ioc_debug_save_ftrc(struct bfa_ioc *ioc)
1854{
1855 int tlen;
1856
1857 if (ioc->dbg_fwsave_once) {
1858 ioc->dbg_fwsave_once = 0;
1859 if (ioc->dbg_fwsave_len) {
1860 tlen = ioc->dbg_fwsave_len;
1861 bfa_nw_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
1862 }
1863 }
1864}
1865
1866/**
1867 * Retrieve saved firmware trace from a prior IOC failure.
1868 */
1869int
1870bfa_nw_ioc_debug_fwsave(struct bfa_ioc *ioc, void *trcdata, int *trclen)
1871{
1872 int tlen;
1873
1874 if (ioc->dbg_fwsave_len == 0)
1875 return BFA_STATUS_ENOFSAVE;
1876
1877 tlen = *trclen;
1878 if (tlen > ioc->dbg_fwsave_len)
1879 tlen = ioc->dbg_fwsave_len;
1880
1881 memcpy(trcdata, ioc->dbg_fwsave, tlen);
1882 *trclen = tlen;
1883 return BFA_STATUS_OK;
1884}
1885
Rasesh Mody1d32f762010-12-23 21:45:09 +00001886static void
1887bfa_ioc_fail_notify(struct bfa_ioc *ioc)
1888{
Rasesh Mody1d32f762010-12-23 21:45:09 +00001889 /**
1890 * Notify driver and common modules registered for notification.
1891 */
1892 ioc->cbfn->hbfail_cbfn(ioc->bfa);
Rasesh Modybd5a92e2011-07-22 08:07:42 +00001893 bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED);
Krishna Gudipati7afc5db2011-12-22 13:30:19 +00001894 bfa_nw_ioc_debug_save_ftrc(ioc);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001895}
1896
Rasesh Modyaafd5c22011-09-27 10:39:09 +00001897/**
1898 * IOCPF to IOC interface
1899 */
Rasesh Mody1d32f762010-12-23 21:45:09 +00001900static void
1901bfa_ioc_pf_enabled(struct bfa_ioc *ioc)
1902{
1903 bfa_fsm_send_event(ioc, IOC_E_ENABLED);
1904}
1905
1906static void
1907bfa_ioc_pf_disabled(struct bfa_ioc *ioc)
1908{
1909 bfa_fsm_send_event(ioc, IOC_E_DISABLED);
1910}
1911
1912static void
Rasesh Mody1d32f762010-12-23 21:45:09 +00001913bfa_ioc_pf_failed(struct bfa_ioc *ioc)
1914{
Rasesh Modyf374b362011-07-22 08:07:46 +00001915 bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
Rasesh Mody1d32f762010-12-23 21:45:09 +00001916}
1917
1918static void
Rasesh Mody078086f2011-08-08 16:21:39 +00001919bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc)
1920{
1921 bfa_fsm_send_event(ioc, IOC_E_HWFAILED);
1922}
1923
1924static void
Rasesh Mody1d32f762010-12-23 21:45:09 +00001925bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc)
1926{
1927 /**
1928 * Provide enable completion callback and AEN notification.
1929 */
1930 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
1931}
1932
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001933/**
1934 * IOC public
1935 */
Rasesh Mody8a891422010-08-25 23:00:27 -07001936static enum bfa_status
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001937bfa_ioc_pll_init(struct bfa_ioc *ioc)
1938{
1939 /*
1940 * Hold semaphore so that nobody can access the chip during init.
1941 */
Rasesh Mody8a891422010-08-25 23:00:27 -07001942 bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001943
1944 bfa_ioc_pll_init_asic(ioc);
1945
1946 ioc->pllinit = true;
Jing Huange491c772012-04-04 05:42:08 +00001947
1948 /* Initialize LMEM */
1949 bfa_ioc_lmem_init(ioc);
1950
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001951 /*
1952 * release semaphore.
1953 */
Rasesh Mody8a891422010-08-25 23:00:27 -07001954 bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001955
1956 return BFA_STATUS_OK;
1957}
1958
1959/**
1960 * Interface used by diag module to do firmware boot with memory test
1961 * as the entry vector.
1962 */
Rasesh Mody8a891422010-08-25 23:00:27 -07001963static void
Rasesh Mody078086f2011-08-08 16:21:39 +00001964bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
1965 u32 boot_env)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001966{
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001967 bfa_ioc_stats(ioc, ioc_boots);
1968
1969 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1970 return;
1971
1972 /**
1973 * Initialize IOC state of all functions on a chip reset.
1974 */
Rasesh Mody078086f2011-08-08 16:21:39 +00001975 if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) {
1976 writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate);
1977 writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001978 } else {
Rasesh Mody078086f2011-08-08 16:21:39 +00001979 writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate);
1980 writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001981 }
1982
1983 bfa_ioc_msgflush(ioc);
Rasesh Mody79ea6c82011-04-14 08:05:18 +00001984 bfa_ioc_download_fw(ioc, boot_type, boot_env);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001985 bfa_ioc_lpu_start(ioc);
1986}
1987
1988/**
1989 * Enable/disable IOC failure auto recovery.
1990 */
1991void
Rasesh Mody8a891422010-08-25 23:00:27 -07001992bfa_nw_ioc_auto_recover(bool auto_recover)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001993{
Rasesh Mody8a891422010-08-25 23:00:27 -07001994 bfa_nw_auto_recover = auto_recover;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001995}
1996
Rasesh Mody078086f2011-08-08 16:21:39 +00001997static bool
Rasesh Mody8b230ed2010-08-23 20:24:12 -07001998bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
1999{
2000 u32 *msgp = mbmsg;
2001 u32 r32;
2002 int i;
2003
Rasesh Mody078086f2011-08-08 16:21:39 +00002004 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
2005 if ((r32 & 1) == 0)
2006 return false;
2007
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002008 /**
2009 * read the MBOX msg
2010 */
2011 for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
2012 i++) {
2013 r32 = readl(ioc->ioc_regs.lpu_mbox +
2014 i * sizeof(u32));
2015 msgp[i] = htonl(r32);
2016 }
2017
2018 /**
2019 * turn off mailbox interrupt by clearing mailbox status
2020 */
2021 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
2022 readl(ioc->ioc_regs.lpu_mbox_cmd);
Rasesh Mody078086f2011-08-08 16:21:39 +00002023
2024 return true;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002025}
2026
Rasesh Mody8a891422010-08-25 23:00:27 -07002027static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002028bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
2029{
2030 union bfi_ioc_i2h_msg_u *msg;
Rasesh Mody1d32f762010-12-23 21:45:09 +00002031 struct bfa_iocpf *iocpf = &ioc->iocpf;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002032
2033 msg = (union bfi_ioc_i2h_msg_u *) m;
2034
2035 bfa_ioc_stats(ioc, ioc_isrs);
2036
2037 switch (msg->mh.msg_id) {
2038 case BFI_IOC_I2H_HBEAT:
2039 break;
2040
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002041 case BFI_IOC_I2H_ENABLE_REPLY:
Rasesh Mody078086f2011-08-08 16:21:39 +00002042 bfa_ioc_enable_reply(ioc,
2043 (enum bfa_mode)msg->fw_event.port_mode,
2044 msg->fw_event.cap_bm);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002045 break;
2046
2047 case BFI_IOC_I2H_DISABLE_REPLY:
Rasesh Mody1d32f762010-12-23 21:45:09 +00002048 bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_DISABLE);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002049 break;
2050
2051 case BFI_IOC_I2H_GETATTR_REPLY:
2052 bfa_ioc_getattr_reply(ioc);
2053 break;
2054
2055 default:
2056 BUG_ON(1);
2057 }
2058}
2059
2060/**
2061 * IOC attach time initialization and setup.
2062 *
2063 * @param[in] ioc memory for IOC
2064 * @param[in] bfa driver instance structure
2065 */
2066void
Rasesh Mody8a891422010-08-25 23:00:27 -07002067bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002068{
2069 ioc->bfa = bfa;
2070 ioc->cbfn = cbfn;
2071 ioc->fcmode = false;
2072 ioc->pllinit = false;
2073 ioc->dbg_fwsave_once = true;
Rasesh Mody1d32f762010-12-23 21:45:09 +00002074 ioc->iocpf.ioc = ioc;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002075
2076 bfa_ioc_mbox_attach(ioc);
Rasesh Modybd5a92e2011-07-22 08:07:42 +00002077 INIT_LIST_HEAD(&ioc->notify_q);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002078
Rasesh Mody1d32f762010-12-23 21:45:09 +00002079 bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit);
2080 bfa_fsm_send_event(ioc, IOC_E_RESET);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002081}
2082
2083/**
2084 * Driver detach time IOC cleanup.
2085 */
2086void
Rasesh Mody8a891422010-08-25 23:00:27 -07002087bfa_nw_ioc_detach(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002088{
2089 bfa_fsm_send_event(ioc, IOC_E_DETACH);
Rasesh Mody078086f2011-08-08 16:21:39 +00002090
2091 /* Done with detach, empty the notify_q. */
2092 INIT_LIST_HEAD(&ioc->notify_q);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002093}
2094
2095/**
2096 * Setup IOC PCI properties.
2097 *
2098 * @param[in] pcidev PCI device information for this IOC
2099 */
2100void
Rasesh Mody8a891422010-08-25 23:00:27 -07002101bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
Rasesh Mody078086f2011-08-08 16:21:39 +00002102 enum bfi_pcifn_class clscode)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002103{
Rasesh Mody078086f2011-08-08 16:21:39 +00002104 ioc->clscode = clscode;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002105 ioc->pcidev = *pcidev;
Rasesh Mody078086f2011-08-08 16:21:39 +00002106
2107 /**
2108 * Initialize IOC and device personality
2109 */
2110 ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC;
2111 ioc->asic_mode = BFI_ASIC_MODE_FC;
2112
2113 switch (pcidev->device_id) {
2114 case PCI_DEVICE_ID_BROCADE_CT:
2115 ioc->asic_gen = BFI_ASIC_GEN_CT;
2116 ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2117 ioc->asic_mode = BFI_ASIC_MODE_ETH;
2118 ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA;
2119 ioc->ad_cap_bm = BFA_CM_CNA;
2120 break;
2121
Rasesh Mody586b28162011-09-27 10:39:08 +00002122 case BFA_PCI_DEVICE_ID_CT2:
2123 ioc->asic_gen = BFI_ASIC_GEN_CT2;
2124 if (clscode == BFI_PCIFN_CLASS_FC &&
2125 pcidev->ssid == BFA_PCI_CT2_SSID_FC) {
2126 ioc->asic_mode = BFI_ASIC_MODE_FC16;
2127 ioc->fcmode = true;
2128 ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_HBA;
2129 ioc->ad_cap_bm = BFA_CM_HBA;
2130 } else {
2131 ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH;
2132 ioc->asic_mode = BFI_ASIC_MODE_ETH;
2133 if (pcidev->ssid == BFA_PCI_CT2_SSID_FCoE) {
2134 ioc->port_mode =
2135 ioc->port_mode_cfg = BFA_MODE_CNA;
2136 ioc->ad_cap_bm = BFA_CM_CNA;
2137 } else {
2138 ioc->port_mode =
2139 ioc->port_mode_cfg = BFA_MODE_NIC;
2140 ioc->ad_cap_bm = BFA_CM_NIC;
2141 }
2142 }
2143 break;
2144
Rasesh Mody078086f2011-08-08 16:21:39 +00002145 default:
2146 BUG_ON(1);
2147 }
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002148
Rasesh Modybe3a84d2011-09-27 10:39:05 +00002149 /**
2150 * Set asic specific interfaces.
2151 */
2152 if (ioc->asic_gen == BFI_ASIC_GEN_CT)
2153 bfa_nw_ioc_set_ct_hwif(ioc);
Rasesh Mody70f1438122011-10-04 23:04:01 -04002154 else {
2155 WARN_ON(ioc->asic_gen != BFI_ASIC_GEN_CT2);
Rasesh Modybe3a84d2011-09-27 10:39:05 +00002156 bfa_nw_ioc_set_ct2_hwif(ioc);
Rasesh Mody70f1438122011-10-04 23:04:01 -04002157 bfa_nw_ioc_ct2_poweron(ioc);
2158 }
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002159
2160 bfa_ioc_map_port(ioc);
2161 bfa_ioc_reg_init(ioc);
2162}
2163
2164/**
2165 * Initialize IOC dma memory
2166 *
2167 * @param[in] dm_kva kernel virtual address of IOC dma memory
2168 * @param[in] dm_pa physical address of IOC dma memory
2169 */
2170void
Rasesh Mody8a891422010-08-25 23:00:27 -07002171bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002172{
2173 /**
2174 * dma memory for firmware attribute
2175 */
2176 ioc->attr_dma.kva = dm_kva;
2177 ioc->attr_dma.pa = dm_pa;
2178 ioc->attr = (struct bfi_ioc_attr *) dm_kva;
2179}
2180
2181/**
2182 * Return size of dma memory required.
2183 */
2184u32
Rasesh Mody8a891422010-08-25 23:00:27 -07002185bfa_nw_ioc_meminfo(void)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002186{
2187 return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ);
2188}
2189
2190void
Rasesh Mody8a891422010-08-25 23:00:27 -07002191bfa_nw_ioc_enable(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002192{
2193 bfa_ioc_stats(ioc, ioc_enables);
2194 ioc->dbg_fwsave_once = true;
2195
2196 bfa_fsm_send_event(ioc, IOC_E_ENABLE);
2197}
2198
2199void
Rasesh Mody8a891422010-08-25 23:00:27 -07002200bfa_nw_ioc_disable(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002201{
2202 bfa_ioc_stats(ioc, ioc_disables);
2203 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
2204}
2205
Krishna Gudipati7afc5db2011-12-22 13:30:19 +00002206/**
2207 * Initialize memory for saving firmware trace.
2208 */
2209void
2210bfa_nw_ioc_debug_memclaim(struct bfa_ioc *ioc, void *dbg_fwsave)
2211{
2212 ioc->dbg_fwsave = dbg_fwsave;
2213 ioc->dbg_fwsave_len = ioc->iocpf.auto_recover ? BNA_DBG_FWTRC_LEN : 0;
2214}
2215
Rasesh Mody8a891422010-08-25 23:00:27 -07002216static u32
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002217bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
2218{
2219 return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
2220}
2221
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002222/**
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002223 * Register mailbox message handler function, to be called by common modules
2224 */
2225void
Rasesh Mody8a891422010-08-25 23:00:27 -07002226bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002227 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
2228{
2229 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
2230
2231 mod->mbhdlr[mc].cbfn = cbfn;
2232 mod->mbhdlr[mc].cbarg = cbarg;
2233}
2234
2235/**
2236 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
2237 * Responsibility of caller to serialize
2238 *
2239 * @param[in] ioc IOC instance
2240 * @param[i] cmd Mailbox command
2241 */
Rasesh Modyaf027a32011-08-08 16:21:35 +00002242bool
2243bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd,
2244 bfa_mbox_cmd_cbfn_t cbfn, void *cbarg)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002245{
2246 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
2247 u32 stat;
2248
Rasesh Modyaf027a32011-08-08 16:21:35 +00002249 cmd->cbfn = cbfn;
2250 cmd->cbarg = cbarg;
2251
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002252 /**
2253 * If a previous command is pending, queue new command
2254 */
2255 if (!list_empty(&mod->cmd_q)) {
2256 list_add_tail(&cmd->qe, &mod->cmd_q);
Rasesh Modyaf027a32011-08-08 16:21:35 +00002257 return true;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002258 }
2259
2260 /**
2261 * If mailbox is busy, queue command for poll timer
2262 */
2263 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
2264 if (stat) {
2265 list_add_tail(&cmd->qe, &mod->cmd_q);
Rasesh Modyaf027a32011-08-08 16:21:35 +00002266 return true;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002267 }
2268
2269 /**
2270 * mailbox is free -- queue command to firmware
2271 */
2272 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
Rasesh Modybd5a92e2011-07-22 08:07:42 +00002273
Rasesh Modyaf027a32011-08-08 16:21:35 +00002274 return false;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002275}
2276
2277/**
2278 * Handle mailbox interrupts
2279 */
2280void
Rasesh Mody8a891422010-08-25 23:00:27 -07002281bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002282{
2283 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
2284 struct bfi_mbmsg m;
2285 int mc;
2286
Rasesh Mody078086f2011-08-08 16:21:39 +00002287 if (bfa_ioc_msgget(ioc, &m)) {
2288 /**
2289 * Treat IOC message class as special.
2290 */
2291 mc = m.mh.msg_class;
2292 if (mc == BFI_MC_IOC) {
2293 bfa_ioc_isr(ioc, &m);
2294 return;
2295 }
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002296
Rasesh Mody078086f2011-08-08 16:21:39 +00002297 if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
2298 return;
2299
2300 mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002301 }
2302
Rasesh Mody078086f2011-08-08 16:21:39 +00002303 bfa_ioc_lpu_read_stat(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002304
Rasesh Mody078086f2011-08-08 16:21:39 +00002305 /**
2306 * Try to send pending mailbox commands
2307 */
2308 bfa_ioc_mbox_poll(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002309}
2310
2311void
Rasesh Mody8a891422010-08-25 23:00:27 -07002312bfa_nw_ioc_error_isr(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002313{
Rasesh Mody9b08a4f2011-07-22 08:07:48 +00002314 bfa_ioc_stats(ioc, ioc_hbfails);
2315 bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002316 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
2317}
2318
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002319/**
Rasesh Modybd5a92e2011-07-22 08:07:42 +00002320 * return true if IOC is disabled
2321 */
2322bool
2323bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc)
2324{
2325 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
2326 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
2327}
2328
2329/**
Krishna Gudipati72a97302011-12-22 13:29:45 +00002330 * return true if IOC is operational
2331 */
2332bool
2333bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
2334{
2335 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
2336}
2337
2338/**
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002339 * Add to IOC heartbeat failure notification queue. To be used by common
2340 * modules such as cee, port, diag.
2341 */
2342void
Rasesh Modybd5a92e2011-07-22 08:07:42 +00002343bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
2344 struct bfa_ioc_notify *notify)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002345{
Rasesh Modybd5a92e2011-07-22 08:07:42 +00002346 list_add_tail(&notify->qe, &ioc->notify_q);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002347}
2348
2349#define BFA_MFG_NAME "Brocade"
Rasesh Mody8a891422010-08-25 23:00:27 -07002350static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002351bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
2352 struct bfa_adapter_attr *ad_attr)
2353{
2354 struct bfi_ioc_attr *ioc_attr;
2355
2356 ioc_attr = ioc->attr;
2357
2358 bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
2359 bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
2360 bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
2361 bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
2362 memcpy(&ad_attr->vpd, &ioc_attr->vpd,
2363 sizeof(struct bfa_mfg_vpd));
2364
2365 ad_attr->nports = bfa_ioc_get_nports(ioc);
2366 ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
2367
2368 bfa_ioc_get_adapter_model(ioc, ad_attr->model);
2369 /* For now, model descr uses same model string */
2370 bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
2371
2372 ad_attr->card_type = ioc_attr->card_type;
2373 ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
2374
2375 if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
2376 ad_attr->prototype = 1;
2377 else
2378 ad_attr->prototype = 0;
2379
2380 ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
Rasesh Mody8a891422010-08-25 23:00:27 -07002381 ad_attr->mac = bfa_nw_ioc_get_mac(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002382
2383 ad_attr->pcie_gen = ioc_attr->pcie_gen;
2384 ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
2385 ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
2386 ad_attr->asic_rev = ioc_attr->asic_rev;
2387
2388 bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002389}
2390
Rasesh Mody8a891422010-08-25 23:00:27 -07002391static enum bfa_ioc_type
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002392bfa_ioc_get_type(struct bfa_ioc *ioc)
2393{
Rasesh Mody078086f2011-08-08 16:21:39 +00002394 if (ioc->clscode == BFI_PCIFN_CLASS_ETH)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002395 return BFA_IOC_TYPE_LL;
Rasesh Mody078086f2011-08-08 16:21:39 +00002396
2397 BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC));
2398
2399 return (ioc->attr->port_mode == BFI_PORT_MODE_FC)
2400 ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002401}
2402
Rasesh Mody8a891422010-08-25 23:00:27 -07002403static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002404bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
2405{
2406 memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
2407 memcpy(serial_num,
2408 (void *)ioc->attr->brcd_serialnum,
2409 BFA_ADAPTER_SERIAL_NUM_LEN);
2410}
2411
Rasesh Mody8a891422010-08-25 23:00:27 -07002412static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002413bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
2414{
2415 memset(fw_ver, 0, BFA_VERSION_LEN);
2416 memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
2417}
2418
Rasesh Mody8a891422010-08-25 23:00:27 -07002419static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002420bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
2421{
2422 BUG_ON(!(chip_rev));
2423
2424 memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
2425
2426 chip_rev[0] = 'R';
2427 chip_rev[1] = 'e';
2428 chip_rev[2] = 'v';
2429 chip_rev[3] = '-';
2430 chip_rev[4] = ioc->attr->asic_rev;
2431 chip_rev[5] = '\0';
2432}
2433
Rasesh Mody8a891422010-08-25 23:00:27 -07002434static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002435bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
2436{
2437 memset(optrom_ver, 0, BFA_VERSION_LEN);
2438 memcpy(optrom_ver, ioc->attr->optrom_version,
2439 BFA_VERSION_LEN);
2440}
2441
Rasesh Mody8a891422010-08-25 23:00:27 -07002442static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002443bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
2444{
2445 memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
2446 memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
2447}
2448
Rasesh Mody8a891422010-08-25 23:00:27 -07002449static void
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002450bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
2451{
2452 struct bfi_ioc_attr *ioc_attr;
2453
2454 BUG_ON(!(model));
2455 memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
2456
2457 ioc_attr = ioc->attr;
2458
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002459 snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
2460 BFA_MFG_NAME, ioc_attr->card_type);
2461}
2462
Rasesh Mody8a891422010-08-25 23:00:27 -07002463static enum bfa_ioc_state
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002464bfa_ioc_get_state(struct bfa_ioc *ioc)
2465{
Rasesh Mody1d32f762010-12-23 21:45:09 +00002466 enum bfa_iocpf_state iocpf_st;
2467 enum bfa_ioc_state ioc_st = bfa_sm_to_state(ioc_sm_table, ioc->fsm);
2468
2469 if (ioc_st == BFA_IOC_ENABLING ||
2470 ioc_st == BFA_IOC_FAIL || ioc_st == BFA_IOC_INITFAIL) {
2471
2472 iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2473
2474 switch (iocpf_st) {
2475 case BFA_IOCPF_SEMWAIT:
2476 ioc_st = BFA_IOC_SEMWAIT;
2477 break;
2478
2479 case BFA_IOCPF_HWINIT:
2480 ioc_st = BFA_IOC_HWINIT;
2481 break;
2482
2483 case BFA_IOCPF_FWMISMATCH:
2484 ioc_st = BFA_IOC_FWMISMATCH;
2485 break;
2486
2487 case BFA_IOCPF_FAIL:
2488 ioc_st = BFA_IOC_FAIL;
2489 break;
2490
2491 case BFA_IOCPF_INITFAIL:
2492 ioc_st = BFA_IOC_INITFAIL;
2493 break;
2494
2495 default:
2496 break;
2497 }
2498 }
2499 return ioc_st;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002500}
2501
2502void
Rasesh Mody8a891422010-08-25 23:00:27 -07002503bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002504{
2505 memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));
2506
2507 ioc_attr->state = bfa_ioc_get_state(ioc);
2508 ioc_attr->port_id = ioc->port_id;
Rasesh Mody078086f2011-08-08 16:21:39 +00002509 ioc_attr->port_mode = ioc->port_mode;
2510
2511 ioc_attr->port_mode_cfg = ioc->port_mode_cfg;
2512 ioc_attr->cap_bm = ioc->ad_cap_bm;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002513
2514 ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
2515
2516 bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
2517
2518 ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
2519 ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
2520 bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
2521}
2522
2523/**
2524 * WWN public
2525 */
Rasesh Mody8a891422010-08-25 23:00:27 -07002526static u64
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002527bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
2528{
2529 return ioc->attr->pwwn;
2530}
2531
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002532mac_t
Rasesh Mody8a891422010-08-25 23:00:27 -07002533bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002534{
Rasesh Mody2c7d3822010-12-23 21:45:06 +00002535 return ioc->attr->mac;
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002536}
2537
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002538/**
2539 * Firmware failure detected. Start recovery actions.
2540 */
2541static void
2542bfa_ioc_recover(struct bfa_ioc *ioc)
2543{
Rasesh Mody1e581482011-04-04 08:29:59 +00002544 pr_crit("Heart Beat of IOC has failed\n");
2545 bfa_ioc_stats(ioc, ioc_hbfails);
Rasesh Mody9b08a4f2011-07-22 08:07:48 +00002546 bfa_ioc_stats_hb_count(ioc, ioc->hb_count);
Rasesh Mody1e581482011-04-04 08:29:59 +00002547 bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002548}
2549
2550static void
2551bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
2552{
2553 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
2554 return;
Rasesh Mody1d32f762010-12-23 21:45:09 +00002555}
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002556
Rasesh Mody1d32f762010-12-23 21:45:09 +00002557/**
2558 * @dg hal_iocpf_pvt BFA IOC PF private functions
2559 * @{
2560 */
2561
2562static void
2563bfa_iocpf_enable(struct bfa_ioc *ioc)
2564{
2565 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_ENABLE);
2566}
2567
2568static void
2569bfa_iocpf_disable(struct bfa_ioc *ioc)
2570{
2571 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_DISABLE);
2572}
2573
2574static void
2575bfa_iocpf_fail(struct bfa_ioc *ioc)
2576{
2577 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
2578}
2579
2580static void
2581bfa_iocpf_initfail(struct bfa_ioc *ioc)
2582{
2583 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
2584}
2585
2586static void
2587bfa_iocpf_getattrfail(struct bfa_ioc *ioc)
2588{
2589 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
2590}
2591
2592static void
2593bfa_iocpf_stop(struct bfa_ioc *ioc)
2594{
2595 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP);
2596}
2597
2598void
2599bfa_nw_iocpf_timeout(void *ioc_arg)
2600{
2601 struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
Rasesh Mody078086f2011-08-08 16:21:39 +00002602 enum bfa_iocpf_state iocpf_st;
Rasesh Mody1d32f762010-12-23 21:45:09 +00002603
Rasesh Mody078086f2011-08-08 16:21:39 +00002604 iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm);
2605
2606 if (iocpf_st == BFA_IOCPF_HWINIT)
2607 bfa_ioc_poll_fwinit(ioc);
2608 else
2609 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT);
Rasesh Mody1d32f762010-12-23 21:45:09 +00002610}
2611
2612void
2613bfa_nw_iocpf_sem_timeout(void *ioc_arg)
2614{
2615 struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
2616
2617 bfa_ioc_hw_sem_get(ioc);
Rasesh Mody8b230ed2010-08-23 20:24:12 -07002618}
Rasesh Mody078086f2011-08-08 16:21:39 +00002619
2620static void
2621bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)
2622{
2623 u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate);
2624
2625 if (fwstate == BFI_IOC_DISABLED) {
2626 bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY);
2627 return;
2628 }
2629
2630 if (ioc->iocpf.poll_time >= BFA_IOC_TOV) {
2631 bfa_nw_iocpf_timeout(ioc);
2632 } else {
2633 ioc->iocpf.poll_time += BFA_IOC_POLL_TOV;
2634 mod_timer(&ioc->iocpf_timer, jiffies +
2635 msecs_to_jiffies(BFA_IOC_POLL_TOV));
2636 }
2637}
Krishna Gudipati72a97302011-12-22 13:29:45 +00002638
2639/*
2640 * Flash module specific
2641 */
2642
2643/*
2644 * FLASH DMA buffer should be big enough to hold both MFG block and
2645 * asic block(64k) at the same time and also should be 2k aligned to
2646 * avoid write segement to cross sector boundary.
2647 */
2648#define BFA_FLASH_SEG_SZ 2048
2649#define BFA_FLASH_DMA_BUF_SZ \
2650 roundup(0x010000 + sizeof(struct bfa_mfg_block), BFA_FLASH_SEG_SZ)
2651
2652static void
2653bfa_flash_cb(struct bfa_flash *flash)
2654{
2655 flash->op_busy = 0;
2656 if (flash->cbfn)
2657 flash->cbfn(flash->cbarg, flash->status);
2658}
2659
2660static void
2661bfa_flash_notify(void *cbarg, enum bfa_ioc_event event)
2662{
2663 struct bfa_flash *flash = cbarg;
2664
2665 switch (event) {
2666 case BFA_IOC_E_DISABLED:
2667 case BFA_IOC_E_FAILED:
2668 if (flash->op_busy) {
2669 flash->status = BFA_STATUS_IOC_FAILURE;
2670 flash->cbfn(flash->cbarg, flash->status);
2671 flash->op_busy = 0;
2672 }
2673 break;
2674 default:
2675 break;
2676 }
2677}
2678
2679/*
2680 * Send flash write request.
2681 *
2682 * @param[in] cbarg - callback argument
2683 */
2684static void
2685bfa_flash_write_send(struct bfa_flash *flash)
2686{
2687 struct bfi_flash_write_req *msg =
2688 (struct bfi_flash_write_req *) flash->mb.msg;
2689 u32 len;
2690
2691 msg->type = be32_to_cpu(flash->type);
2692 msg->instance = flash->instance;
2693 msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
2694 len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
2695 flash->residue : BFA_FLASH_DMA_BUF_SZ;
2696 msg->length = be32_to_cpu(len);
2697
2698 /* indicate if it's the last msg of the whole write operation */
2699 msg->last = (len == flash->residue) ? 1 : 0;
2700
2701 bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
2702 bfa_ioc_portid(flash->ioc));
2703 bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
2704 memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
2705 bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);
2706
2707 flash->residue -= len;
2708 flash->offset += len;
2709}
2710
2711/*
2712 * Send flash read request.
2713 *
2714 * @param[in] cbarg - callback argument
2715 */
2716static void
2717bfa_flash_read_send(void *cbarg)
2718{
2719 struct bfa_flash *flash = cbarg;
2720 struct bfi_flash_read_req *msg =
2721 (struct bfi_flash_read_req *) flash->mb.msg;
2722 u32 len;
2723
2724 msg->type = be32_to_cpu(flash->type);
2725 msg->instance = flash->instance;
2726 msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
2727 len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
2728 flash->residue : BFA_FLASH_DMA_BUF_SZ;
2729 msg->length = be32_to_cpu(len);
2730 bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
2731 bfa_ioc_portid(flash->ioc));
2732 bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
2733 bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);
2734}
2735
2736/*
2737 * Process flash response messages upon receiving interrupts.
2738 *
2739 * @param[in] flasharg - flash structure
2740 * @param[in] msg - message structure
2741 */
2742static void
2743bfa_flash_intr(void *flasharg, struct bfi_mbmsg *msg)
2744{
2745 struct bfa_flash *flash = flasharg;
2746 u32 status;
2747
2748 union {
2749 struct bfi_flash_query_rsp *query;
2750 struct bfi_flash_write_rsp *write;
2751 struct bfi_flash_read_rsp *read;
2752 struct bfi_mbmsg *msg;
2753 } m;
2754
2755 m.msg = msg;
2756
2757 /* receiving response after ioc failure */
2758 if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT)
2759 return;
2760
2761 switch (msg->mh.msg_id) {
2762 case BFI_FLASH_I2H_QUERY_RSP:
2763 status = be32_to_cpu(m.query->status);
2764 if (status == BFA_STATUS_OK) {
2765 u32 i;
2766 struct bfa_flash_attr *attr, *f;
2767
2768 attr = (struct bfa_flash_attr *) flash->ubuf;
2769 f = (struct bfa_flash_attr *) flash->dbuf_kva;
2770 attr->status = be32_to_cpu(f->status);
2771 attr->npart = be32_to_cpu(f->npart);
2772 for (i = 0; i < attr->npart; i++) {
2773 attr->part[i].part_type =
2774 be32_to_cpu(f->part[i].part_type);
2775 attr->part[i].part_instance =
2776 be32_to_cpu(f->part[i].part_instance);
2777 attr->part[i].part_off =
2778 be32_to_cpu(f->part[i].part_off);
2779 attr->part[i].part_size =
2780 be32_to_cpu(f->part[i].part_size);
2781 attr->part[i].part_len =
2782 be32_to_cpu(f->part[i].part_len);
2783 attr->part[i].part_status =
2784 be32_to_cpu(f->part[i].part_status);
2785 }
2786 }
2787 flash->status = status;
2788 bfa_flash_cb(flash);
2789 break;
2790 case BFI_FLASH_I2H_WRITE_RSP:
2791 status = be32_to_cpu(m.write->status);
2792 if (status != BFA_STATUS_OK || flash->residue == 0) {
2793 flash->status = status;
2794 bfa_flash_cb(flash);
2795 } else
2796 bfa_flash_write_send(flash);
2797 break;
2798 case BFI_FLASH_I2H_READ_RSP:
2799 status = be32_to_cpu(m.read->status);
2800 if (status != BFA_STATUS_OK) {
2801 flash->status = status;
2802 bfa_flash_cb(flash);
2803 } else {
2804 u32 len = be32_to_cpu(m.read->length);
2805 memcpy(flash->ubuf + flash->offset,
2806 flash->dbuf_kva, len);
2807 flash->residue -= len;
2808 flash->offset += len;
2809 if (flash->residue == 0) {
2810 flash->status = status;
2811 bfa_flash_cb(flash);
2812 } else
2813 bfa_flash_read_send(flash);
2814 }
2815 break;
2816 case BFI_FLASH_I2H_BOOT_VER_RSP:
2817 case BFI_FLASH_I2H_EVENT:
2818 break;
2819 default:
2820 WARN_ON(1);
2821 }
2822}
2823
2824/*
2825 * Flash memory info API.
2826 */
2827u32
2828bfa_nw_flash_meminfo(void)
2829{
2830 return roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
2831}
2832
2833/*
2834 * Flash attach API.
2835 *
2836 * @param[in] flash - flash structure
2837 * @param[in] ioc - ioc structure
2838 * @param[in] dev - device structure
2839 */
2840void
2841bfa_nw_flash_attach(struct bfa_flash *flash, struct bfa_ioc *ioc, void *dev)
2842{
2843 flash->ioc = ioc;
2844 flash->cbfn = NULL;
2845 flash->cbarg = NULL;
2846 flash->op_busy = 0;
2847
2848 bfa_nw_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
2849 bfa_q_qe_init(&flash->ioc_notify);
2850 bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
2851 list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);
2852}
2853
2854/*
2855 * Claim memory for flash
2856 *
2857 * @param[in] flash - flash structure
2858 * @param[in] dm_kva - pointer to virtual memory address
2859 * @param[in] dm_pa - physical memory address
2860 */
2861void
2862bfa_nw_flash_memclaim(struct bfa_flash *flash, u8 *dm_kva, u64 dm_pa)
2863{
2864 flash->dbuf_kva = dm_kva;
2865 flash->dbuf_pa = dm_pa;
2866 memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
2867 dm_kva += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
2868 dm_pa += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
2869}
2870
2871/*
2872 * Get flash attribute.
2873 *
2874 * @param[in] flash - flash structure
2875 * @param[in] attr - flash attribute structure
2876 * @param[in] cbfn - callback function
2877 * @param[in] cbarg - callback argument
2878 *
2879 * Return status.
2880 */
2881enum bfa_status
2882bfa_nw_flash_get_attr(struct bfa_flash *flash, struct bfa_flash_attr *attr,
2883 bfa_cb_flash cbfn, void *cbarg)
2884{
2885 struct bfi_flash_query_req *msg =
2886 (struct bfi_flash_query_req *) flash->mb.msg;
2887
2888 if (!bfa_nw_ioc_is_operational(flash->ioc))
2889 return BFA_STATUS_IOC_NON_OP;
2890
2891 if (flash->op_busy)
2892 return BFA_STATUS_DEVBUSY;
2893
2894 flash->op_busy = 1;
2895 flash->cbfn = cbfn;
2896 flash->cbarg = cbarg;
2897 flash->ubuf = (u8 *) attr;
2898
2899 bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
2900 bfa_ioc_portid(flash->ioc));
2901 bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr), flash->dbuf_pa);
2902 bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);
2903
2904 return BFA_STATUS_OK;
2905}
2906
2907/*
2908 * Update flash partition.
2909 *
2910 * @param[in] flash - flash structure
2911 * @param[in] type - flash partition type
2912 * @param[in] instance - flash partition instance
2913 * @param[in] buf - update data buffer
2914 * @param[in] len - data buffer length
2915 * @param[in] offset - offset relative to the partition starting address
2916 * @param[in] cbfn - callback function
2917 * @param[in] cbarg - callback argument
2918 *
2919 * Return status.
2920 */
2921enum bfa_status
2922bfa_nw_flash_update_part(struct bfa_flash *flash, u32 type, u8 instance,
2923 void *buf, u32 len, u32 offset,
2924 bfa_cb_flash cbfn, void *cbarg)
2925{
2926 if (!bfa_nw_ioc_is_operational(flash->ioc))
2927 return BFA_STATUS_IOC_NON_OP;
2928
2929 /*
2930 * 'len' must be in word (4-byte) boundary
2931 */
2932 if (!len || (len & 0x03))
2933 return BFA_STATUS_FLASH_BAD_LEN;
2934
2935 if (type == BFA_FLASH_PART_MFG)
2936 return BFA_STATUS_EINVAL;
2937
2938 if (flash->op_busy)
2939 return BFA_STATUS_DEVBUSY;
2940
2941 flash->op_busy = 1;
2942 flash->cbfn = cbfn;
2943 flash->cbarg = cbarg;
2944 flash->type = type;
2945 flash->instance = instance;
2946 flash->residue = len;
2947 flash->offset = 0;
2948 flash->addr_off = offset;
2949 flash->ubuf = buf;
2950
2951 bfa_flash_write_send(flash);
2952
2953 return BFA_STATUS_OK;
2954}
2955
2956/*
2957 * Read flash partition.
2958 *
2959 * @param[in] flash - flash structure
2960 * @param[in] type - flash partition type
2961 * @param[in] instance - flash partition instance
2962 * @param[in] buf - read data buffer
2963 * @param[in] len - data buffer length
2964 * @param[in] offset - offset relative to the partition starting address
2965 * @param[in] cbfn - callback function
2966 * @param[in] cbarg - callback argument
2967 *
2968 * Return status.
2969 */
2970enum bfa_status
2971bfa_nw_flash_read_part(struct bfa_flash *flash, u32 type, u8 instance,
2972 void *buf, u32 len, u32 offset,
2973 bfa_cb_flash cbfn, void *cbarg)
2974{
2975 if (!bfa_nw_ioc_is_operational(flash->ioc))
2976 return BFA_STATUS_IOC_NON_OP;
2977
2978 /*
2979 * 'len' must be in word (4-byte) boundary
2980 */
2981 if (!len || (len & 0x03))
2982 return BFA_STATUS_FLASH_BAD_LEN;
2983
2984 if (flash->op_busy)
2985 return BFA_STATUS_DEVBUSY;
2986
2987 flash->op_busy = 1;
2988 flash->cbfn = cbfn;
2989 flash->cbarg = cbarg;
2990 flash->type = type;
2991 flash->instance = instance;
2992 flash->residue = len;
2993 flash->offset = 0;
2994 flash->addr_off = offset;
2995 flash->ubuf = buf;
2996
2997 bfa_flash_read_send(flash);
2998
2999 return BFA_STATUS_OK;
3000}