aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bna/bfa_ioc.c
diff options
context:
space:
mode:
authorRasesh Mody <rmody@brocade.com>2010-08-23 23:24:12 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-23 23:24:12 -0400
commit8b230ed8ec96c933047dd0625cf95f739e4939a6 (patch)
tree517e761a804a2b2f9631b755abcbf525240b916e /drivers/net/bna/bfa_ioc.c
parent231cc2aaf14bad3b2325be0b19b8385ff5e75485 (diff)
bna: Brocade 10Gb Ethernet device driver
This is patch 1/6 which contains linux driver source for Brocade's BR1010/BR1020 10Gb CEE capable ethernet adapter. Signed-off-by: Debashis Dutt <ddutt@brocade.com> Signed-off-by: Rasesh Mody <rmody@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bna/bfa_ioc.c')
-rw-r--r--drivers/net/bna/bfa_ioc.c1839
1 files changed, 1839 insertions, 0 deletions
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c
new file mode 100644
index 000000000000..cdc2cb1597ec
--- /dev/null
+++ b/drivers/net/bna/bfa_ioc.c
@@ -0,0 +1,1839 @@
1/*
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"
20#include "cna.h"
21#include "bfi.h"
22#include "bfi_ctreg.h"
23#include "bfa_defs.h"
24
25/**
26 * IOC local definitions
27 */
28
29#define bfa_ioc_timer_start(__ioc) \
30 mod_timer(&(__ioc)->ioc_timer, jiffies + \
31 msecs_to_jiffies(BFA_IOC_TOV))
32#define bfa_ioc_timer_stop(__ioc) del_timer(&(__ioc)->ioc_timer)
33
34#define bfa_ioc_recovery_timer_start(__ioc) \
35 mod_timer(&(__ioc)->ioc_timer, jiffies + \
36 msecs_to_jiffies(BFA_IOC_TOV_RECOVER))
37
38#define bfa_sem_timer_start(__ioc) \
39 mod_timer(&(__ioc)->sem_timer, jiffies + \
40 msecs_to_jiffies(BFA_IOC_HWSEM_TOV))
41#define bfa_sem_timer_stop(__ioc) del_timer(&(__ioc)->sem_timer)
42
43#define bfa_hb_timer_start(__ioc) \
44 mod_timer(&(__ioc)->hb_timer, jiffies + \
45 msecs_to_jiffies(BFA_IOC_HB_TOV))
46#define bfa_hb_timer_stop(__ioc) del_timer(&(__ioc)->hb_timer)
47
48/**
49 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
50 */
51
52#define bfa_ioc_firmware_lock(__ioc) \
53 ((__ioc)->ioc_hwif->ioc_firmware_lock(__ioc))
54#define bfa_ioc_firmware_unlock(__ioc) \
55 ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc))
56#define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc))
57#define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
58#define bfa_ioc_notify_hbfail(__ioc) \
59 ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc))
60
61#define bfa_ioc_is_optrom(__ioc) \
62 (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ)
63
64#define bfa_ioc_mbox_cmd_pending(__ioc) \
65 (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \
66 readl((__ioc)->ioc_regs.hfn_mbox_cmd))
67
68bool bfa_auto_recover = true;
69
70/*
71 * forward declarations
72 */
73static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc);
74static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc);
75static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force);
76static void bfa_ioc_send_enable(struct bfa_ioc *ioc);
77static void bfa_ioc_send_disable(struct bfa_ioc *ioc);
78static void bfa_ioc_send_getattr(struct bfa_ioc *ioc);
79static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc);
80static void bfa_ioc_hb_stop(struct bfa_ioc *ioc);
81static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force);
82static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc);
83static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc);
84static void bfa_ioc_recover(struct bfa_ioc *ioc);
85static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc);
86static void bfa_ioc_disable_comp(struct bfa_ioc *ioc);
87static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc);
88
89/**
90 * IOC state machine events
91 */
92enum ioc_event {
93 IOC_E_ENABLE = 1, /*!< IOC enable request */
94 IOC_E_DISABLE = 2, /*!< IOC disable request */
95 IOC_E_TIMEOUT = 3, /*!< f/w response timeout */
96 IOC_E_FWREADY = 4, /*!< f/w initialization done */
97 IOC_E_FWRSP_GETATTR = 5, /*!< IOC get attribute response */
98 IOC_E_FWRSP_ENABLE = 6, /*!< enable f/w response */
99 IOC_E_FWRSP_DISABLE = 7, /*!< disable f/w response */
100 IOC_E_HBFAIL = 8, /*!< heartbeat failure */
101 IOC_E_HWERROR = 9, /*!< hardware error interrupt */
102 IOC_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */
103 IOC_E_DETACH = 11, /*!< driver detach cleanup */
104};
105
106bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc, enum ioc_event);
107bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc, enum ioc_event);
108bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc, enum ioc_event);
109bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc, enum ioc_event);
110bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc, enum ioc_event);
111bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc, enum ioc_event);
112bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc, enum ioc_event);
113bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc, enum ioc_event);
114bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc, enum ioc_event);
115bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc, enum ioc_event);
116bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event);
117bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event);
118
119static struct bfa_sm_table ioc_sm_table[] = {
120 {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET},
121 {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH},
122 {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH},
123 {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT},
124 {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT},
125 {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT},
126 {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
127 {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
128 {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL},
129 {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL},
130 {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
131 {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
132};
133
134/**
135 * Reset entry actions -- initialize state machine
136 */
137static void
138bfa_ioc_sm_reset_entry(struct bfa_ioc *ioc)
139{
140 ioc->retry_count = 0;
141 ioc->auto_recover = bfa_auto_recover;
142}
143
144/**
145 * Beginning state. IOC is in reset state.
146 */
147static void
148bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event)
149{
150 switch (event) {
151 case IOC_E_ENABLE:
152 bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
153 break;
154
155 case IOC_E_DISABLE:
156 bfa_ioc_disable_comp(ioc);
157 break;
158
159 case IOC_E_DETACH:
160 break;
161
162 default:
163 bfa_sm_fault(ioc, event);
164 }
165}
166
167/**
168 * Semaphore should be acquired for version check.
169 */
170static void
171bfa_ioc_sm_fwcheck_entry(struct bfa_ioc *ioc)
172{
173 bfa_ioc_hw_sem_get(ioc);
174}
175
176/**
177 * Awaiting h/w semaphore to continue with version check.
178 */
179static void
180bfa_ioc_sm_fwcheck(struct bfa_ioc *ioc, enum ioc_event event)
181{
182 switch (event) {
183 case IOC_E_SEMLOCKED:
184 if (bfa_ioc_firmware_lock(ioc)) {
185 ioc->retry_count = 0;
186 bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
187 } else {
188 bfa_ioc_hw_sem_release(ioc);
189 bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch);
190 }
191 break;
192
193 case IOC_E_DISABLE:
194 bfa_ioc_disable_comp(ioc);
195 /* fall through */
196
197 case IOC_E_DETACH:
198 bfa_ioc_hw_sem_get_cancel(ioc);
199 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
200 break;
201
202 case IOC_E_FWREADY:
203 break;
204
205 default:
206 bfa_sm_fault(ioc, event);
207 }
208}
209
210/**
211 * Notify enable completion callback and generate mismatch AEN.
212 */
213static void
214bfa_ioc_sm_mismatch_entry(struct bfa_ioc *ioc)
215{
216 /**
217 * Provide enable completion callback and AEN notification only once.
218 */
219 if (ioc->retry_count == 0)
220 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
221 ioc->retry_count++;
222 bfa_ioc_timer_start(ioc);
223}
224
225/**
226 * Awaiting firmware version match.
227 */
228static void
229bfa_ioc_sm_mismatch(struct bfa_ioc *ioc, enum ioc_event event)
230{
231 switch (event) {
232 case IOC_E_TIMEOUT:
233 bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck);
234 break;
235
236 case IOC_E_DISABLE:
237 bfa_ioc_disable_comp(ioc);
238 /* fall through */
239
240 case IOC_E_DETACH:
241 bfa_ioc_timer_stop(ioc);
242 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
243 break;
244
245 case IOC_E_FWREADY:
246 break;
247
248 default:
249 bfa_sm_fault(ioc, event);
250 }
251}
252
253/**
254 * Request for semaphore.
255 */
256static void
257bfa_ioc_sm_semwait_entry(struct bfa_ioc *ioc)
258{
259 bfa_ioc_hw_sem_get(ioc);
260}
261
262/**
263 * Awaiting semaphore for h/w initialzation.
264 */
265static void
266bfa_ioc_sm_semwait(struct bfa_ioc *ioc, enum ioc_event event)
267{
268 switch (event) {
269 case IOC_E_SEMLOCKED:
270 ioc->retry_count = 0;
271 bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
272 break;
273
274 case IOC_E_DISABLE:
275 bfa_ioc_hw_sem_get_cancel(ioc);
276 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
277 break;
278
279 default:
280 bfa_sm_fault(ioc, event);
281 }
282}
283
284static void
285bfa_ioc_sm_hwinit_entry(struct bfa_ioc *ioc)
286{
287 bfa_ioc_timer_start(ioc);
288 bfa_ioc_reset(ioc, false);
289}
290
291/**
292 * @brief
293 * Hardware is being initialized. Interrupts are enabled.
294 * Holding hardware semaphore lock.
295 */
296static void
297bfa_ioc_sm_hwinit(struct bfa_ioc *ioc, enum ioc_event event)
298{
299 switch (event) {
300 case IOC_E_FWREADY:
301 bfa_ioc_timer_stop(ioc);
302 bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling);
303 break;
304
305 case IOC_E_HWERROR:
306 bfa_ioc_timer_stop(ioc);
307 /* fall through */
308
309 case IOC_E_TIMEOUT:
310 ioc->retry_count++;
311 if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
312 bfa_ioc_timer_start(ioc);
313 bfa_ioc_reset(ioc, true);
314 break;
315 }
316
317 bfa_ioc_hw_sem_release(ioc);
318 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
319 break;
320
321 case IOC_E_DISABLE:
322 bfa_ioc_hw_sem_release(ioc);
323 bfa_ioc_timer_stop(ioc);
324 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
325 break;
326
327 default:
328 bfa_sm_fault(ioc, event);
329 }
330}
331
332static void
333bfa_ioc_sm_enabling_entry(struct bfa_ioc *ioc)
334{
335 bfa_ioc_timer_start(ioc);
336 bfa_ioc_send_enable(ioc);
337}
338
339/**
340 * Host IOC function is being enabled, awaiting response from firmware.
341 * Semaphore is acquired.
342 */
343static void
344bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event)
345{
346 switch (event) {
347 case IOC_E_FWRSP_ENABLE:
348 bfa_ioc_timer_stop(ioc);
349 bfa_ioc_hw_sem_release(ioc);
350 bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
351 break;
352
353 case IOC_E_HWERROR:
354 bfa_ioc_timer_stop(ioc);
355 /* fall through */
356
357 case IOC_E_TIMEOUT:
358 ioc->retry_count++;
359 if (ioc->retry_count < BFA_IOC_HWINIT_MAX) {
360 writel(BFI_IOC_UNINIT,
361 ioc->ioc_regs.ioc_fwstate);
362 bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit);
363 break;
364 }
365
366 bfa_ioc_hw_sem_release(ioc);
367 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
368 break;
369
370 case IOC_E_DISABLE:
371 bfa_ioc_timer_stop(ioc);
372 bfa_ioc_hw_sem_release(ioc);
373 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
374 break;
375
376 case IOC_E_FWREADY:
377 bfa_ioc_send_enable(ioc);
378 break;
379
380 default:
381 bfa_sm_fault(ioc, event);
382 }
383}
384
385static void
386bfa_ioc_sm_getattr_entry(struct bfa_ioc *ioc)
387{
388 bfa_ioc_timer_start(ioc);
389 bfa_ioc_send_getattr(ioc);
390}
391
392/**
393 * @brief
394 * IOC configuration in progress. Timer is active.
395 */
396static void
397bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event)
398{
399 switch (event) {
400 case IOC_E_FWRSP_GETATTR:
401 bfa_ioc_timer_stop(ioc);
402 bfa_ioc_check_attr_wwns(ioc);
403 bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
404 break;
405
406 case IOC_E_HWERROR:
407 bfa_ioc_timer_stop(ioc);
408 /* fall through */
409
410 case IOC_E_TIMEOUT:
411 bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
412 break;
413
414 case IOC_E_DISABLE:
415 bfa_ioc_timer_stop(ioc);
416 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
417 break;
418
419 default:
420 bfa_sm_fault(ioc, event);
421 }
422}
423
424static void
425bfa_ioc_sm_op_entry(struct bfa_ioc *ioc)
426{
427 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
428 bfa_ioc_hb_monitor(ioc);
429}
430
431static void
432bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event)
433{
434 switch (event) {
435 case IOC_E_ENABLE:
436 break;
437
438 case IOC_E_DISABLE:
439 bfa_ioc_hb_stop(ioc);
440 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
441 break;
442
443 case IOC_E_HWERROR:
444 case IOC_E_FWREADY:
445 /**
446 * Hard error or IOC recovery by other function.
447 * Treat it same as heartbeat failure.
448 */
449 bfa_ioc_hb_stop(ioc);
450 /* !!! fall through !!! */
451
452 case IOC_E_HBFAIL:
453 bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail);
454 break;
455
456 default:
457 bfa_sm_fault(ioc, event);
458 }
459}
460
461static void
462bfa_ioc_sm_disabling_entry(struct bfa_ioc *ioc)
463{
464 bfa_ioc_timer_start(ioc);
465 bfa_ioc_send_disable(ioc);
466}
467
468/**
469 * IOC is being disabled
470 */
471static void
472bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event)
473{
474 switch (event) {
475 case IOC_E_FWRSP_DISABLE:
476 bfa_ioc_timer_stop(ioc);
477 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
478 break;
479
480 case IOC_E_HWERROR:
481 bfa_ioc_timer_stop(ioc);
482 /*
483 * !!! fall through !!!
484 */
485
486 case IOC_E_TIMEOUT:
487 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
488 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
489 break;
490
491 default:
492 bfa_sm_fault(ioc, event);
493 }
494}
495
496/**
497 * IOC disable completion entry.
498 */
499static void
500bfa_ioc_sm_disabled_entry(struct bfa_ioc *ioc)
501{
502 bfa_ioc_disable_comp(ioc);
503}
504
505static void
506bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event)
507{
508 switch (event) {
509 case IOC_E_ENABLE:
510 bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
511 break;
512
513 case IOC_E_DISABLE:
514 ioc->cbfn->disable_cbfn(ioc->bfa);
515 break;
516
517 case IOC_E_FWREADY:
518 break;
519
520 case IOC_E_DETACH:
521 bfa_ioc_firmware_unlock(ioc);
522 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
523 break;
524
525 default:
526 bfa_sm_fault(ioc, event);
527 }
528}
529
530static void
531bfa_ioc_sm_initfail_entry(struct bfa_ioc *ioc)
532{
533 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
534 bfa_ioc_timer_start(ioc);
535}
536
537/**
538 * @brief
539 * Hardware initialization failed.
540 */
541static void
542bfa_ioc_sm_initfail(struct bfa_ioc *ioc, enum ioc_event event)
543{
544 switch (event) {
545 case IOC_E_DISABLE:
546 bfa_ioc_timer_stop(ioc);
547 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
548 break;
549
550 case IOC_E_DETACH:
551 bfa_ioc_timer_stop(ioc);
552 bfa_ioc_firmware_unlock(ioc);
553 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
554 break;
555
556 case IOC_E_TIMEOUT:
557 bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
558 break;
559
560 default:
561 bfa_sm_fault(ioc, event);
562 }
563}
564
565static void
566bfa_ioc_sm_hbfail_entry(struct bfa_ioc *ioc)
567{
568 struct list_head *qe;
569 struct bfa_ioc_hbfail_notify *notify;
570
571 /**
572 * Mark IOC as failed in hardware and stop firmware.
573 */
574 bfa_ioc_lpu_stop(ioc);
575 writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate);
576
577 /**
578 * Notify other functions on HB failure.
579 */
580 bfa_ioc_notify_hbfail(ioc);
581
582 /**
583 * Notify driver and common modules registered for notification.
584 */
585 ioc->cbfn->hbfail_cbfn(ioc->bfa);
586 list_for_each(qe, &ioc->hb_notify_q) {
587 notify = (struct bfa_ioc_hbfail_notify *) qe;
588 notify->cbfn(notify->cbarg);
589 }
590
591 /**
592 * Flush any queued up mailbox requests.
593 */
594 bfa_ioc_mbox_hbfail(ioc);
595
596 /**
597 * Trigger auto-recovery after a delay.
598 */
599 if (ioc->auto_recover)
600 mod_timer(&ioc->ioc_timer, jiffies +
601 msecs_to_jiffies(BFA_IOC_TOV_RECOVER));
602}
603
604/**
605 * @brief
606 * IOC heartbeat failure.
607 */
608static void
609bfa_ioc_sm_hbfail(struct bfa_ioc *ioc, enum ioc_event event)
610{
611 switch (event) {
612
613 case IOC_E_ENABLE:
614 ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
615 break;
616
617 case IOC_E_DISABLE:
618 if (ioc->auto_recover)
619 bfa_ioc_timer_stop(ioc);
620 bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled);
621 break;
622
623 case IOC_E_TIMEOUT:
624 bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait);
625 break;
626
627 case IOC_E_FWREADY:
628 /**
629 * Recovery is already initiated by other function.
630 */
631 break;
632
633 case IOC_E_HWERROR:
634 /*
635 * HB failure notification, ignore.
636 */
637 break;
638 default:
639 bfa_sm_fault(ioc, event);
640 }
641}
642
643/**
644 * BFA IOC private functions
645 */
646
647static void
648bfa_ioc_disable_comp(struct bfa_ioc *ioc)
649{
650 struct list_head *qe;
651 struct bfa_ioc_hbfail_notify *notify;
652
653 ioc->cbfn->disable_cbfn(ioc->bfa);
654
655 /**
656 * Notify common modules registered for notification.
657 */
658 list_for_each(qe, &ioc->hb_notify_q) {
659 notify = (struct bfa_ioc_hbfail_notify *) qe;
660 notify->cbfn(notify->cbarg);
661 }
662}
663
664void
665bfa_ioc_sem_timeout(void *ioc_arg)
666{
667 struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
668
669 bfa_ioc_hw_sem_get(ioc);
670}
671
672bool
673bfa_ioc_sem_get(void __iomem *sem_reg)
674{
675 u32 r32;
676 int cnt = 0;
677#define BFA_SEM_SPINCNT 3000
678
679 r32 = readl(sem_reg);
680
681 while (r32 && (cnt < BFA_SEM_SPINCNT)) {
682 cnt++;
683 udelay(2);
684 r32 = readl(sem_reg);
685 }
686
687 if (r32 == 0)
688 return true;
689
690 BUG_ON(!(cnt < BFA_SEM_SPINCNT));
691 return false;
692}
693
694void
695bfa_ioc_sem_release(void __iomem *sem_reg)
696{
697 writel(1, sem_reg);
698}
699
700static void
701bfa_ioc_hw_sem_get(struct bfa_ioc *ioc)
702{
703 u32 r32;
704
705 /**
706 * First read to the semaphore register will return 0, subsequent reads
707 * will return 1. Semaphore is released by writing 1 to the register
708 */
709 r32 = readl(ioc->ioc_regs.ioc_sem_reg);
710 if (r32 == 0) {
711 bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED);
712 return;
713 }
714
715 mod_timer(&ioc->sem_timer, jiffies +
716 msecs_to_jiffies(BFA_IOC_HWSEM_TOV));
717}
718
719void
720bfa_ioc_hw_sem_release(struct bfa_ioc *ioc)
721{
722 writel(1, ioc->ioc_regs.ioc_sem_reg);
723}
724
725static void
726bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc)
727{
728 del_timer(&ioc->sem_timer);
729}
730
731/**
732 * @brief
733 * Initialize LPU local memory (aka secondary memory / SRAM)
734 */
735static void
736bfa_ioc_lmem_init(struct bfa_ioc *ioc)
737{
738 u32 pss_ctl;
739 int i;
740#define PSS_LMEM_INIT_TIME 10000
741
742 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
743 pss_ctl &= ~__PSS_LMEM_RESET;
744 pss_ctl |= __PSS_LMEM_INIT_EN;
745
746 /*
747 * i2c workaround 12.5khz clock
748 */
749 pss_ctl |= __PSS_I2C_CLK_DIV(3UL);
750 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
751
752 /**
753 * wait for memory initialization to be complete
754 */
755 i = 0;
756 do {
757 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
758 i++;
759 } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME));
760
761 /**
762 * If memory initialization is not successful, IOC timeout will catch
763 * such failures.
764 */
765 BUG_ON(!(pss_ctl & __PSS_LMEM_INIT_DONE));
766
767 pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN);
768 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
769}
770
771static void
772bfa_ioc_lpu_start(struct bfa_ioc *ioc)
773{
774 u32 pss_ctl;
775
776 /**
777 * Take processor out of reset.
778 */
779 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
780 pss_ctl &= ~__PSS_LPU0_RESET;
781
782 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
783}
784
785static void
786bfa_ioc_lpu_stop(struct bfa_ioc *ioc)
787{
788 u32 pss_ctl;
789
790 /**
791 * Put processors in reset.
792 */
793 pss_ctl = readl(ioc->ioc_regs.pss_ctl_reg);
794 pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET);
795
796 writel(pss_ctl, ioc->ioc_regs.pss_ctl_reg);
797}
798
799/**
800 * Get driver and firmware versions.
801 */
802void
803bfa_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
804{
805 u32 pgnum, pgoff;
806 u32 loff = 0;
807 int i;
808 u32 *fwsig = (u32 *) fwhdr;
809
810 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
811 pgoff = bfa_ioc_smem_pgoff(ioc, loff);
812 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
813
814 for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr) / sizeof(u32));
815 i++) {
816 fwsig[i] =
817 swab32(readl((loff) + (ioc->ioc_regs.smem_page_start)));
818 loff += sizeof(u32);
819 }
820}
821
822/**
823 * Returns TRUE if same.
824 */
825bool
826bfa_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
827{
828 struct bfi_ioc_image_hdr *drv_fwhdr;
829 int i;
830
831 drv_fwhdr = (struct bfi_ioc_image_hdr *)
832 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
833
834 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
835 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i])
836 return false;
837 }
838
839 return true;
840}
841
842/**
843 * Return true if current running version is valid. Firmware signature and
844 * execution context (driver/bios) must match.
845 */
846static bool
847bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
848{
849 struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
850
851 /**
852 * If bios/efi boot (flash based) -- return true
853 */
854 if (bfa_ioc_is_optrom(ioc))
855 return true;
856
857 bfa_ioc_fwver_get(ioc, &fwhdr);
858 drv_fwhdr = (struct bfi_ioc_image_hdr *)
859 bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0);
860
861 if (fwhdr.signature != drv_fwhdr->signature)
862 return false;
863
864 if (fwhdr.exec != drv_fwhdr->exec)
865 return false;
866
867 return bfa_ioc_fwver_cmp(ioc, &fwhdr);
868}
869
870/**
871 * Conditionally flush any pending message from firmware at start.
872 */
873static void
874bfa_ioc_msgflush(struct bfa_ioc *ioc)
875{
876 u32 r32;
877
878 r32 = readl(ioc->ioc_regs.lpu_mbox_cmd);
879 if (r32)
880 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
881}
882
883/**
884 * @img ioc_init_logic.jpg
885 */
886static void
887bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
888{
889 enum bfi_ioc_state ioc_fwstate;
890 bool fwvalid;
891
892 ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
893
894 if (force)
895 ioc_fwstate = BFI_IOC_UNINIT;
896
897 /**
898 * check if firmware is valid
899 */
900 fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
901 false : bfa_ioc_fwver_valid(ioc);
902
903 if (!fwvalid) {
904 bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
905 return;
906 }
907
908 /**
909 * If hardware initialization is in progress (initialized by other IOC),
910 * just wait for an initialization completion interrupt.
911 */
912 if (ioc_fwstate == BFI_IOC_INITING) {
913 ioc->cbfn->reset_cbfn(ioc->bfa);
914 return;
915 }
916
917 /**
918 * If IOC function is disabled and firmware version is same,
919 * just re-enable IOC.
920 *
921 * If option rom, IOC must not be in operational state. With
922 * convergence, IOC will be in operational state when 2nd driver
923 * is loaded.
924 */
925 if (ioc_fwstate == BFI_IOC_DISABLED ||
926 (!bfa_ioc_is_optrom(ioc) && ioc_fwstate == BFI_IOC_OP)) {
927 /**
928 * When using MSI-X any pending firmware ready event should
929 * be flushed. Otherwise MSI-X interrupts are not delivered.
930 */
931 bfa_ioc_msgflush(ioc);
932 ioc->cbfn->reset_cbfn(ioc->bfa);
933 bfa_fsm_send_event(ioc, IOC_E_FWREADY);
934 return;
935 }
936
937 /**
938 * Initialize the h/w for any other states.
939 */
940 bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
941}
942
943void
944bfa_ioc_timeout(void *ioc_arg)
945{
946 struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg;
947
948 bfa_fsm_send_event(ioc, IOC_E_TIMEOUT);
949}
950
951void
952bfa_ioc_mbox_send(struct bfa_ioc *ioc, void *ioc_msg, int len)
953{
954 u32 *msgp = (u32 *) ioc_msg;
955 u32 i;
956
957 BUG_ON(!(len <= BFI_IOC_MSGLEN_MAX));
958
959 /*
960 * first write msg to mailbox registers
961 */
962 for (i = 0; i < len / sizeof(u32); i++)
963 writel(cpu_to_le32(msgp[i]),
964 ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
965
966 for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++)
967 writel(0, ioc->ioc_regs.hfn_mbox + i * sizeof(u32));
968
969 /*
970 * write 1 to mailbox CMD to trigger LPU event
971 */
972 writel(1, ioc->ioc_regs.hfn_mbox_cmd);
973 (void) readl(ioc->ioc_regs.hfn_mbox_cmd);
974}
975
976static void
977bfa_ioc_send_enable(struct bfa_ioc *ioc)
978{
979 struct bfi_ioc_ctrl_req enable_req;
980 struct timeval tv;
981
982 bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ,
983 bfa_ioc_portid(ioc));
984 enable_req.ioc_class = ioc->ioc_mc;
985 do_gettimeofday(&tv);
986 enable_req.tv_sec = ntohl(tv.tv_sec);
987 bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req));
988}
989
990static void
991bfa_ioc_send_disable(struct bfa_ioc *ioc)
992{
993 struct bfi_ioc_ctrl_req disable_req;
994
995 bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ,
996 bfa_ioc_portid(ioc));
997 bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req));
998}
999
1000static void
1001bfa_ioc_send_getattr(struct bfa_ioc *ioc)
1002{
1003 struct bfi_ioc_getattr_req attr_req;
1004
1005 bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ,
1006 bfa_ioc_portid(ioc));
1007 bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa);
1008 bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req));
1009}
1010
1011void
1012bfa_ioc_hb_check(void *cbarg)
1013{
1014 struct bfa_ioc *ioc = cbarg;
1015 u32 hb_count;
1016
1017 hb_count = readl(ioc->ioc_regs.heartbeat);
1018 if (ioc->hb_count == hb_count) {
1019 pr_crit("Firmware heartbeat failure at %d", hb_count);
1020 bfa_ioc_recover(ioc);
1021 return;
1022 } else {
1023 ioc->hb_count = hb_count;
1024 }
1025
1026 bfa_ioc_mbox_poll(ioc);
1027 mod_timer(&ioc->hb_timer, jiffies +
1028 msecs_to_jiffies(BFA_IOC_HB_TOV));
1029}
1030
1031static void
1032bfa_ioc_hb_monitor(struct bfa_ioc *ioc)
1033{
1034 ioc->hb_count = readl(ioc->ioc_regs.heartbeat);
1035 mod_timer(&ioc->hb_timer, jiffies +
1036 msecs_to_jiffies(BFA_IOC_HB_TOV));
1037}
1038
1039static void
1040bfa_ioc_hb_stop(struct bfa_ioc *ioc)
1041{
1042 del_timer(&ioc->hb_timer);
1043}
1044
1045/**
1046 * @brief
1047 * Initiate a full firmware download.
1048 */
1049static void
1050bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
1051 u32 boot_param)
1052{
1053 u32 *fwimg;
1054 u32 pgnum, pgoff;
1055 u32 loff = 0;
1056 u32 chunkno = 0;
1057 u32 i;
1058
1059 /**
1060 * Initialize LMEM first before code download
1061 */
1062 bfa_ioc_lmem_init(ioc);
1063
1064 /**
1065 * Flash based firmware boot
1066 */
1067 if (bfa_ioc_is_optrom(ioc))
1068 boot_type = BFI_BOOT_TYPE_FLASH;
1069 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno);
1070
1071 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
1072 pgoff = bfa_ioc_smem_pgoff(ioc, loff);
1073
1074 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1075
1076 for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) {
1077 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1078 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
1079 fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc),
1080 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
1081 }
1082
1083 /**
1084 * write smem
1085 */
1086 writel((swab32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])),
1087 ((ioc->ioc_regs.smem_page_start) + (loff)));
1088
1089 loff += sizeof(u32);
1090
1091 /**
1092 * handle page offset wrap around
1093 */
1094 loff = PSS_SMEM_PGOFF(loff);
1095 if (loff == 0) {
1096 pgnum++;
1097 writel(pgnum,
1098 ioc->ioc_regs.host_page_num_fn);
1099 }
1100 }
1101
1102 writel(bfa_ioc_smem_pgnum(ioc, 0),
1103 ioc->ioc_regs.host_page_num_fn);
1104
1105 /*
1106 * Set boot type and boot param at the end.
1107 */
1108 writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start)
1109 + (BFI_BOOT_TYPE_OFF)));
1110 writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start)
1111 + (BFI_BOOT_PARAM_OFF)));
1112}
1113
1114static void
1115bfa_ioc_reset(struct bfa_ioc *ioc, bool force)
1116{
1117 bfa_ioc_hwinit(ioc, force);
1118}
1119
1120/**
1121 * @brief
1122 * Update BFA configuration from firmware configuration.
1123 */
1124static void
1125bfa_ioc_getattr_reply(struct bfa_ioc *ioc)
1126{
1127 struct bfi_ioc_attr *attr = ioc->attr;
1128
1129 attr->adapter_prop = ntohl(attr->adapter_prop);
1130 attr->card_type = ntohl(attr->card_type);
1131 attr->maxfrsize = ntohs(attr->maxfrsize);
1132
1133 bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR);
1134}
1135
1136/**
1137 * Attach time initialization of mbox logic.
1138 */
1139static void
1140bfa_ioc_mbox_attach(struct bfa_ioc *ioc)
1141{
1142 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1143 int mc;
1144
1145 INIT_LIST_HEAD(&mod->cmd_q);
1146 for (mc = 0; mc < BFI_MC_MAX; mc++) {
1147 mod->mbhdlr[mc].cbfn = NULL;
1148 mod->mbhdlr[mc].cbarg = ioc->bfa;
1149 }
1150}
1151
1152/**
1153 * Mbox poll timer -- restarts any pending mailbox requests.
1154 */
1155static void
1156bfa_ioc_mbox_poll(struct bfa_ioc *ioc)
1157{
1158 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1159 struct bfa_mbox_cmd *cmd;
1160 u32 stat;
1161
1162 /**
1163 * If no command pending, do nothing
1164 */
1165 if (list_empty(&mod->cmd_q))
1166 return;
1167
1168 /**
1169 * If previous command is not yet fetched by firmware, do nothing
1170 */
1171 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
1172 if (stat)
1173 return;
1174
1175 /**
1176 * Enqueue command to firmware.
1177 */
1178 bfa_q_deq(&mod->cmd_q, &cmd);
1179 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1180}
1181
1182/**
1183 * Cleanup any pending requests.
1184 */
1185static void
1186bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc)
1187{
1188 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1189 struct bfa_mbox_cmd *cmd;
1190
1191 while (!list_empty(&mod->cmd_q))
1192 bfa_q_deq(&mod->cmd_q, &cmd);
1193}
1194
1195/**
1196 * IOC public
1197 */
1198enum bfa_status
1199bfa_ioc_pll_init(struct bfa_ioc *ioc)
1200{
1201 /*
1202 * Hold semaphore so that nobody can access the chip during init.
1203 */
1204 bfa_ioc_sem_get(ioc->ioc_regs.ioc_init_sem_reg);
1205
1206 bfa_ioc_pll_init_asic(ioc);
1207
1208 ioc->pllinit = true;
1209 /*
1210 * release semaphore.
1211 */
1212 bfa_ioc_sem_release(ioc->ioc_regs.ioc_init_sem_reg);
1213
1214 return BFA_STATUS_OK;
1215}
1216
1217/**
1218 * Interface used by diag module to do firmware boot with memory test
1219 * as the entry vector.
1220 */
1221void
1222bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
1223{
1224 void __iomem *rb;
1225
1226 bfa_ioc_stats(ioc, ioc_boots);
1227
1228 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1229 return;
1230
1231 /**
1232 * Initialize IOC state of all functions on a chip reset.
1233 */
1234 rb = ioc->pcidev.pci_bar_kva;
1235 if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
1236 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
1237 writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
1238 } else {
1239 writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG));
1240 writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG));
1241 }
1242
1243 bfa_ioc_msgflush(ioc);
1244 bfa_ioc_download_fw(ioc, boot_type, boot_param);
1245
1246 /**
1247 * Enable interrupts just before starting LPU
1248 */
1249 ioc->cbfn->reset_cbfn(ioc->bfa);
1250 bfa_ioc_lpu_start(ioc);
1251}
1252
1253/**
1254 * Enable/disable IOC failure auto recovery.
1255 */
1256void
1257bfa_ioc_auto_recover(bool auto_recover)
1258{
1259 bfa_auto_recover = auto_recover;
1260}
1261
1262bool
1263bfa_ioc_is_operational(struct bfa_ioc *ioc)
1264{
1265 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
1266}
1267
1268bool
1269bfa_ioc_is_initialized(struct bfa_ioc *ioc)
1270{
1271 u32 r32 = readl(ioc->ioc_regs.ioc_fwstate);
1272
1273 return ((r32 != BFI_IOC_UNINIT) &&
1274 (r32 != BFI_IOC_INITING) &&
1275 (r32 != BFI_IOC_MEMTEST));
1276}
1277
1278void
1279bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg)
1280{
1281 u32 *msgp = mbmsg;
1282 u32 r32;
1283 int i;
1284
1285 /**
1286 * read the MBOX msg
1287 */
1288 for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32));
1289 i++) {
1290 r32 = readl(ioc->ioc_regs.lpu_mbox +
1291 i * sizeof(u32));
1292 msgp[i] = htonl(r32);
1293 }
1294
1295 /**
1296 * turn off mailbox interrupt by clearing mailbox status
1297 */
1298 writel(1, ioc->ioc_regs.lpu_mbox_cmd);
1299 readl(ioc->ioc_regs.lpu_mbox_cmd);
1300}
1301
1302void
1303bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m)
1304{
1305 union bfi_ioc_i2h_msg_u *msg;
1306
1307 msg = (union bfi_ioc_i2h_msg_u *) m;
1308
1309 bfa_ioc_stats(ioc, ioc_isrs);
1310
1311 switch (msg->mh.msg_id) {
1312 case BFI_IOC_I2H_HBEAT:
1313 break;
1314
1315 case BFI_IOC_I2H_READY_EVENT:
1316 bfa_fsm_send_event(ioc, IOC_E_FWREADY);
1317 break;
1318
1319 case BFI_IOC_I2H_ENABLE_REPLY:
1320 bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE);
1321 break;
1322
1323 case BFI_IOC_I2H_DISABLE_REPLY:
1324 bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE);
1325 break;
1326
1327 case BFI_IOC_I2H_GETATTR_REPLY:
1328 bfa_ioc_getattr_reply(ioc);
1329 break;
1330
1331 default:
1332 BUG_ON(1);
1333 }
1334}
1335
1336/**
1337 * IOC attach time initialization and setup.
1338 *
1339 * @param[in] ioc memory for IOC
1340 * @param[in] bfa driver instance structure
1341 */
1342void
1343bfa_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn)
1344{
1345 ioc->bfa = bfa;
1346 ioc->cbfn = cbfn;
1347 ioc->fcmode = false;
1348 ioc->pllinit = false;
1349 ioc->dbg_fwsave_once = true;
1350
1351 bfa_ioc_mbox_attach(ioc);
1352 INIT_LIST_HEAD(&ioc->hb_notify_q);
1353
1354 bfa_fsm_set_state(ioc, bfa_ioc_sm_reset);
1355}
1356
1357/**
1358 * Driver detach time IOC cleanup.
1359 */
1360void
1361bfa_ioc_detach(struct bfa_ioc *ioc)
1362{
1363 bfa_fsm_send_event(ioc, IOC_E_DETACH);
1364}
1365
1366/**
1367 * Setup IOC PCI properties.
1368 *
1369 * @param[in] pcidev PCI device information for this IOC
1370 */
1371void
1372bfa_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev,
1373 enum bfi_mclass mc)
1374{
1375 ioc->ioc_mc = mc;
1376 ioc->pcidev = *pcidev;
1377 ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id);
1378 ioc->cna = ioc->ctdev && !ioc->fcmode;
1379
1380 bfa_ioc_set_ct_hwif(ioc);
1381
1382 bfa_ioc_map_port(ioc);
1383 bfa_ioc_reg_init(ioc);
1384}
1385
1386/**
1387 * Initialize IOC dma memory
1388 *
1389 * @param[in] dm_kva kernel virtual address of IOC dma memory
1390 * @param[in] dm_pa physical address of IOC dma memory
1391 */
1392void
1393bfa_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa)
1394{
1395 /**
1396 * dma memory for firmware attribute
1397 */
1398 ioc->attr_dma.kva = dm_kva;
1399 ioc->attr_dma.pa = dm_pa;
1400 ioc->attr = (struct bfi_ioc_attr *) dm_kva;
1401}
1402
1403/**
1404 * Return size of dma memory required.
1405 */
1406u32
1407bfa_ioc_meminfo(void)
1408{
1409 return roundup(sizeof(struct bfi_ioc_attr), BFA_DMA_ALIGN_SZ);
1410}
1411
1412void
1413bfa_ioc_enable(struct bfa_ioc *ioc)
1414{
1415 bfa_ioc_stats(ioc, ioc_enables);
1416 ioc->dbg_fwsave_once = true;
1417
1418 bfa_fsm_send_event(ioc, IOC_E_ENABLE);
1419}
1420
1421void
1422bfa_ioc_disable(struct bfa_ioc *ioc)
1423{
1424 bfa_ioc_stats(ioc, ioc_disables);
1425 bfa_fsm_send_event(ioc, IOC_E_DISABLE);
1426}
1427
1428u32
1429bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr)
1430{
1431 return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr);
1432}
1433
1434u32
1435bfa_ioc_smem_pgoff(struct bfa_ioc *ioc, u32 fmaddr)
1436{
1437 return PSS_SMEM_PGOFF(fmaddr);
1438}
1439
1440/**
1441 * Register mailbox message handler functions
1442 *
1443 * @param[in] ioc IOC instance
1444 * @param[in] mcfuncs message class handler functions
1445 */
1446void
1447bfa_ioc_mbox_register(struct bfa_ioc *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs)
1448{
1449 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1450 int mc;
1451
1452 for (mc = 0; mc < BFI_MC_MAX; mc++)
1453 mod->mbhdlr[mc].cbfn = mcfuncs[mc];
1454}
1455
1456/**
1457 * Register mailbox message handler function, to be called by common modules
1458 */
1459void
1460bfa_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc,
1461 bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg)
1462{
1463 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1464
1465 mod->mbhdlr[mc].cbfn = cbfn;
1466 mod->mbhdlr[mc].cbarg = cbarg;
1467}
1468
1469/**
1470 * Queue a mailbox command request to firmware. Waits if mailbox is busy.
1471 * Responsibility of caller to serialize
1472 *
1473 * @param[in] ioc IOC instance
1474 * @param[i] cmd Mailbox command
1475 */
1476void
1477bfa_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd)
1478{
1479 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1480 u32 stat;
1481
1482 /**
1483 * If a previous command is pending, queue new command
1484 */
1485 if (!list_empty(&mod->cmd_q)) {
1486 list_add_tail(&cmd->qe, &mod->cmd_q);
1487 return;
1488 }
1489
1490 /**
1491 * If mailbox is busy, queue command for poll timer
1492 */
1493 stat = readl(ioc->ioc_regs.hfn_mbox_cmd);
1494 if (stat) {
1495 list_add_tail(&cmd->qe, &mod->cmd_q);
1496 return;
1497 }
1498
1499 /**
1500 * mailbox is free -- queue command to firmware
1501 */
1502 bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg));
1503}
1504
1505/**
1506 * Handle mailbox interrupts
1507 */
1508void
1509bfa_ioc_mbox_isr(struct bfa_ioc *ioc)
1510{
1511 struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod;
1512 struct bfi_mbmsg m;
1513 int mc;
1514
1515 bfa_ioc_msgget(ioc, &m);
1516
1517 /**
1518 * Treat IOC message class as special.
1519 */
1520 mc = m.mh.msg_class;
1521 if (mc == BFI_MC_IOC) {
1522 bfa_ioc_isr(ioc, &m);
1523 return;
1524 }
1525
1526 if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL))
1527 return;
1528
1529 mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m);
1530}
1531
1532void
1533bfa_ioc_error_isr(struct bfa_ioc *ioc)
1534{
1535 bfa_fsm_send_event(ioc, IOC_E_HWERROR);
1536}
1537
1538void
1539bfa_ioc_set_fcmode(struct bfa_ioc *ioc)
1540{
1541 ioc->fcmode = true;
1542 ioc->port_id = bfa_ioc_pcifn(ioc);
1543}
1544
1545/**
1546 * return true if IOC is disabled
1547 */
1548bool
1549bfa_ioc_is_disabled(struct bfa_ioc *ioc)
1550{
1551 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) ||
1552 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled);
1553}
1554
1555/**
1556 * return true if IOC firmware is different.
1557 */
1558bool
1559bfa_ioc_fw_mismatch(struct bfa_ioc *ioc)
1560{
1561 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) ||
1562 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck) ||
1563 bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch);
1564}
1565
1566#define bfa_ioc_state_disabled(__sm) \
1567 (((__sm) == BFI_IOC_UNINIT) || \
1568 ((__sm) == BFI_IOC_INITING) || \
1569 ((__sm) == BFI_IOC_HWINIT) || \
1570 ((__sm) == BFI_IOC_DISABLED) || \
1571 ((__sm) == BFI_IOC_FAIL) || \
1572 ((__sm) == BFI_IOC_CFG_DISABLED))
1573
1574/**
1575 * Check if adapter is disabled -- both IOCs should be in a disabled
1576 * state.
1577 */
1578bool
1579bfa_ioc_adapter_is_disabled(struct bfa_ioc *ioc)
1580{
1581 u32 ioc_state;
1582 void __iomem *rb = ioc->pcidev.pci_bar_kva;
1583
1584 if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled))
1585 return false;
1586
1587 ioc_state = readl(rb + BFA_IOC0_STATE_REG);
1588 if (!bfa_ioc_state_disabled(ioc_state))
1589 return false;
1590
1591 if (ioc->pcidev.device_id != PCI_DEVICE_ID_BROCADE_FC_8G1P) {
1592 ioc_state = readl(rb + BFA_IOC1_STATE_REG);
1593 if (!bfa_ioc_state_disabled(ioc_state))
1594 return false;
1595 }
1596
1597 return true;
1598}
1599
1600/**
1601 * Add to IOC heartbeat failure notification queue. To be used by common
1602 * modules such as cee, port, diag.
1603 */
1604void
1605bfa_ioc_hbfail_register(struct bfa_ioc *ioc,
1606 struct bfa_ioc_hbfail_notify *notify)
1607{
1608 list_add_tail(&notify->qe, &ioc->hb_notify_q);
1609}
1610
1611#define BFA_MFG_NAME "Brocade"
1612void
1613bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc,
1614 struct bfa_adapter_attr *ad_attr)
1615{
1616 struct bfi_ioc_attr *ioc_attr;
1617
1618 ioc_attr = ioc->attr;
1619
1620 bfa_ioc_get_adapter_serial_num(ioc, ad_attr->serial_num);
1621 bfa_ioc_get_adapter_fw_ver(ioc, ad_attr->fw_ver);
1622 bfa_ioc_get_adapter_optrom_ver(ioc, ad_attr->optrom_ver);
1623 bfa_ioc_get_adapter_manufacturer(ioc, ad_attr->manufacturer);
1624 memcpy(&ad_attr->vpd, &ioc_attr->vpd,
1625 sizeof(struct bfa_mfg_vpd));
1626
1627 ad_attr->nports = bfa_ioc_get_nports(ioc);
1628 ad_attr->max_speed = bfa_ioc_speed_sup(ioc);
1629
1630 bfa_ioc_get_adapter_model(ioc, ad_attr->model);
1631 /* For now, model descr uses same model string */
1632 bfa_ioc_get_adapter_model(ioc, ad_attr->model_descr);
1633
1634 ad_attr->card_type = ioc_attr->card_type;
1635 ad_attr->is_mezz = bfa_mfg_is_mezz(ioc_attr->card_type);
1636
1637 if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop))
1638 ad_attr->prototype = 1;
1639 else
1640 ad_attr->prototype = 0;
1641
1642 ad_attr->pwwn = bfa_ioc_get_pwwn(ioc);
1643 ad_attr->mac = bfa_ioc_get_mac(ioc);
1644
1645 ad_attr->pcie_gen = ioc_attr->pcie_gen;
1646 ad_attr->pcie_lanes = ioc_attr->pcie_lanes;
1647 ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig;
1648 ad_attr->asic_rev = ioc_attr->asic_rev;
1649
1650 bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
1651
1652 ad_attr->cna_capable = ioc->cna;
1653 ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna;
1654}
1655
1656enum bfa_ioc_type
1657bfa_ioc_get_type(struct bfa_ioc *ioc)
1658{
1659 if (!ioc->ctdev || ioc->fcmode)
1660 return BFA_IOC_TYPE_FC;
1661 else if (ioc->ioc_mc == BFI_MC_IOCFC)
1662 return BFA_IOC_TYPE_FCoE;
1663 else if (ioc->ioc_mc == BFI_MC_LL)
1664 return BFA_IOC_TYPE_LL;
1665 else {
1666 BUG_ON(!(ioc->ioc_mc == BFI_MC_LL));
1667 return BFA_IOC_TYPE_LL;
1668 }
1669}
1670
1671void
1672bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
1673{
1674 memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
1675 memcpy(serial_num,
1676 (void *)ioc->attr->brcd_serialnum,
1677 BFA_ADAPTER_SERIAL_NUM_LEN);
1678}
1679
1680void
1681bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
1682{
1683 memset(fw_ver, 0, BFA_VERSION_LEN);
1684 memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
1685}
1686
1687void
1688bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
1689{
1690 BUG_ON(!(chip_rev));
1691
1692 memset(chip_rev, 0, BFA_IOC_CHIP_REV_LEN);
1693
1694 chip_rev[0] = 'R';
1695 chip_rev[1] = 'e';
1696 chip_rev[2] = 'v';
1697 chip_rev[3] = '-';
1698 chip_rev[4] = ioc->attr->asic_rev;
1699 chip_rev[5] = '\0';
1700}
1701
1702void
1703bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
1704{
1705 memset(optrom_ver, 0, BFA_VERSION_LEN);
1706 memcpy(optrom_ver, ioc->attr->optrom_version,
1707 BFA_VERSION_LEN);
1708}
1709
1710void
1711bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
1712{
1713 memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
1714 memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
1715}
1716
1717void
1718bfa_ioc_get_adapter_model(struct bfa_ioc *ioc, char *model)
1719{
1720 struct bfi_ioc_attr *ioc_attr;
1721
1722 BUG_ON(!(model));
1723 memset(model, 0, BFA_ADAPTER_MODEL_NAME_LEN);
1724
1725 ioc_attr = ioc->attr;
1726
1727 /**
1728 * model name
1729 */
1730 snprintf(model, BFA_ADAPTER_MODEL_NAME_LEN, "%s-%u",
1731 BFA_MFG_NAME, ioc_attr->card_type);
1732}
1733
1734enum bfa_ioc_state
1735bfa_ioc_get_state(struct bfa_ioc *ioc)
1736{
1737 return bfa_sm_to_state(ioc_sm_table, ioc->fsm);
1738}
1739
1740void
1741bfa_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr)
1742{
1743 memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr));
1744
1745 ioc_attr->state = bfa_ioc_get_state(ioc);
1746 ioc_attr->port_id = ioc->port_id;
1747
1748 ioc_attr->ioc_type = bfa_ioc_get_type(ioc);
1749
1750 bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr);
1751
1752 ioc_attr->pci_attr.device_id = ioc->pcidev.device_id;
1753 ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func;
1754 bfa_ioc_get_pci_chip_rev(ioc, ioc_attr->pci_attr.chip_rev);
1755}
1756
1757/**
1758 * WWN public
1759 */
1760u64
1761bfa_ioc_get_pwwn(struct bfa_ioc *ioc)
1762{
1763 return ioc->attr->pwwn;
1764}
1765
1766u64
1767bfa_ioc_get_nwwn(struct bfa_ioc *ioc)
1768{
1769 return ioc->attr->nwwn;
1770}
1771
1772u64
1773bfa_ioc_get_adid(struct bfa_ioc *ioc)
1774{
1775 return ioc->attr->mfg_pwwn;
1776}
1777
1778mac_t
1779bfa_ioc_get_mac(struct bfa_ioc *ioc)
1780{
1781 /*
1782 * Currently mfg mac is used as FCoE enode mac (not configured by PBC)
1783 */
1784 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_FCoE)
1785 return bfa_ioc_get_mfg_mac(ioc);
1786 else
1787 return ioc->attr->mac;
1788}
1789
1790u64
1791bfa_ioc_get_mfg_pwwn(struct bfa_ioc *ioc)
1792{
1793 return ioc->attr->mfg_pwwn;
1794}
1795
1796u64
1797bfa_ioc_get_mfg_nwwn(struct bfa_ioc *ioc)
1798{
1799 return ioc->attr->mfg_nwwn;
1800}
1801
1802mac_t
1803bfa_ioc_get_mfg_mac(struct bfa_ioc *ioc)
1804{
1805 mac_t m;
1806
1807 m = ioc->attr->mfg_mac;
1808 if (bfa_mfg_is_old_wwn_mac_model(ioc->attr->card_type))
1809 m.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc);
1810 else
1811 bfa_mfg_increment_wwn_mac(&(m.mac[MAC_ADDRLEN-3]),
1812 bfa_ioc_pcifn(ioc));
1813
1814 return m;
1815}
1816
1817bool
1818bfa_ioc_get_fcmode(struct bfa_ioc *ioc)
1819{
1820 return ioc->fcmode || !bfa_asic_id_ct(ioc->pcidev.device_id);
1821}
1822
1823/**
1824 * Firmware failure detected. Start recovery actions.
1825 */
1826static void
1827bfa_ioc_recover(struct bfa_ioc *ioc)
1828{
1829 bfa_ioc_stats(ioc, ioc_hbfails);
1830 bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
1831}
1832
1833static void
1834bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc)
1835{
1836 if (bfa_ioc_get_type(ioc) == BFA_IOC_TYPE_LL)
1837 return;
1838
1839}