diff options
Diffstat (limited to 'drivers/net/bna/bfa_ioc.c')
-rw-r--r-- | drivers/net/bna/bfa_ioc.c | 157 |
1 files changed, 99 insertions, 58 deletions
diff --git a/drivers/net/bna/bfa_ioc.c b/drivers/net/bna/bfa_ioc.c index fcb9bb3169e..126b0aac9f9 100644 --- a/drivers/net/bna/bfa_ioc.c +++ b/drivers/net/bna/bfa_ioc.c @@ -58,6 +58,7 @@ static bool bfa_nw_auto_recover = true; /* * forward declarations */ +static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc); static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc); static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc); static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force); @@ -68,9 +69,10 @@ static void bfa_ioc_hb_monitor(struct bfa_ioc *ioc); static void bfa_ioc_hb_stop(struct bfa_ioc *ioc); static void bfa_ioc_reset(struct bfa_ioc *ioc, bool force); static void bfa_ioc_mbox_poll(struct bfa_ioc *ioc); -static void bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc); +static void bfa_ioc_mbox_flush(struct bfa_ioc *ioc); static void bfa_ioc_recover(struct bfa_ioc *ioc); static void bfa_ioc_check_attr_wwns(struct bfa_ioc *ioc); +static void bfa_ioc_event_notify(struct bfa_ioc *, enum bfa_ioc_event); static void bfa_ioc_disable_comp(struct bfa_ioc *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc); static void bfa_ioc_fail_notify(struct bfa_ioc *ioc); @@ -107,7 +109,7 @@ enum ioc_event { IOC_E_FWRSP_GETATTR = 6, /*!< IOC get attribute response */ IOC_E_DISABLED = 7, /*!< f/w disabled */ IOC_E_INITFAILED = 8, /*!< failure notice by iocpf sm */ - IOC_E_PFAILED = 9, /*!< failure notice by iocpf sm */ + IOC_E_PFFAILED = 9, /*!< failure notice by iocpf sm */ IOC_E_HBFAIL = 10, /*!< heartbeat failure */ IOC_E_HWERROR = 11, /*!< hardware error interrupt */ IOC_E_TIMEOUT = 12, /*!< timeout */ @@ -156,7 +158,7 @@ enum iocpf_event { IOCPF_E_ENABLE = 1, /*!< IOCPF enable request */ IOCPF_E_DISABLE = 2, /*!< IOCPF disable request */ IOCPF_E_STOP = 3, /*!< stop on driver detach */ - IOCPF_E_FWREADY = 4, /*!< f/w initialization done */ + IOCPF_E_FWREADY = 4, /*!< f/w initialization done */ IOCPF_E_FWRSP_ENABLE = 5, /*!< enable f/w response */ IOCPF_E_FWRSP_DISABLE = 6, /*!< disable f/w response */ IOCPF_E_FAIL = 7, /*!< failure notice by ioc sm */ @@ -239,7 +241,7 @@ bfa_ioc_sm_uninit(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -272,7 +274,7 @@ bfa_ioc_sm_reset(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -294,12 +296,12 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); break; - case IOC_E_PFAILED: + case IOC_E_PFFAILED: /* !!! fall through !!! */ case IOC_E_HWERROR: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); - if (event != IOC_E_PFAILED) + if (event != IOC_E_PFFAILED) bfa_iocpf_initfail(ioc); break; @@ -316,7 +318,7 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -344,14 +346,14 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_op); break; - case IOC_E_PFAILED: + case IOC_E_PFFAILED: case IOC_E_HWERROR: del_timer(&ioc->ioc_timer); /* fall through */ case IOC_E_TIMEOUT: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); - if (event != IOC_E_PFAILED) + if (event != IOC_E_PFFAILED) bfa_iocpf_getattrfail(ioc); break; @@ -364,7 +366,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -387,7 +389,7 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; - case IOC_E_PFAILED: + case IOC_E_PFFAILED: case IOC_E_HWERROR: bfa_ioc_hb_stop(ioc); /* !!! fall through !!! */ @@ -398,12 +400,12 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event) else bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); - if (event != IOC_E_PFAILED) + if (event != IOC_E_PFFAILED) bfa_iocpf_fail(ioc); break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -434,7 +436,7 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -465,7 +467,7 @@ bfa_ioc_sm_disabled(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -485,13 +487,13 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event) bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); break; - case IOC_E_PFAILED: + case IOC_E_PFFAILED: case IOC_E_HWERROR: /** * Initialization retry failed. */ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); - if (event != IOC_E_PFAILED) + if (event != IOC_E_PFFAILED) bfa_iocpf_initfail(ioc); break; @@ -512,7 +514,7 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -546,7 +548,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -579,7 +581,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(iocpf->ioc, event); + bfa_sm_fault(event); } } @@ -589,6 +591,7 @@ bfa_iocpf_sm_reset(struct bfa_iocpf *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf *iocpf) { + bfa_ioc_hw_sem_init(iocpf->ioc); bfa_ioc_hw_sem_get(iocpf->ioc); } @@ -631,7 +634,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -675,7 +678,7 @@ bfa_iocpf_sm_mismatch(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -714,7 +717,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -762,7 +765,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -813,7 +816,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -856,7 +859,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -898,7 +901,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -927,7 +930,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -937,6 +940,7 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_disabled_entry(struct bfa_iocpf *iocpf) { + bfa_ioc_mbox_flush(iocpf->ioc); bfa_ioc_pf_disabled(iocpf->ioc); } @@ -957,7 +961,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -1009,7 +1013,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -1038,7 +1042,7 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -1053,7 +1057,7 @@ bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf *iocpf) /** * Flush any queued up mailbox requests. */ - bfa_ioc_mbox_hbfail(iocpf->ioc); + bfa_ioc_mbox_flush(iocpf->ioc); bfa_ioc_hw_sem_get(iocpf->ioc); } @@ -1093,7 +1097,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(ioc, event); + bfa_sm_fault(event); } } @@ -1115,7 +1119,7 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event) break; default: - bfa_sm_fault(iocpf->ioc, event); + bfa_sm_fault(event); } } @@ -1123,23 +1127,28 @@ bfa_iocpf_sm_fail(struct bfa_iocpf *iocpf, enum iocpf_event event) * BFA IOC private functions */ +/** + * Notify common modules registered for notification. + */ static void -bfa_ioc_disable_comp(struct bfa_ioc *ioc) +bfa_ioc_event_notify(struct bfa_ioc *ioc, enum bfa_ioc_event event) { + struct bfa_ioc_notify *notify; struct list_head *qe; - struct bfa_ioc_hbfail_notify *notify; - - ioc->cbfn->disable_cbfn(ioc->bfa); - /** - * Notify common modules registered for notification. - */ - list_for_each(qe, &ioc->hb_notify_q) { - notify = (struct bfa_ioc_hbfail_notify *) qe; - notify->cbfn(notify->cbarg); + list_for_each(qe, &ioc->notify_q) { + notify = (struct bfa_ioc_notify *)qe; + notify->cbfn(notify->cbarg, event); } } +static void +bfa_ioc_disable_comp(struct bfa_ioc *ioc) +{ + ioc->cbfn->disable_cbfn(ioc->bfa); + bfa_ioc_event_notify(ioc, BFA_IOC_E_DISABLED); +} + bool bfa_nw_ioc_sem_get(void __iomem *sem_reg) { @@ -1169,6 +1178,29 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg) } static void +bfa_ioc_hw_sem_init(struct bfa_ioc *ioc) +{ + struct bfi_ioc_image_hdr fwhdr; + u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + if (fwstate == BFI_IOC_UNINIT) + return; + + bfa_nw_ioc_fwver_get(ioc, &fwhdr); + + if (swab32(fwhdr.exec) == BFI_FWBOOT_TYPE_NORMAL) + return; + + writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); + + /* + * Try to lock and then unlock the semaphore. + */ + readl(ioc->ioc_regs.ioc_sem_reg); + writel(1, ioc->ioc_regs.ioc_sem_reg); +} + +static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc) { u32 r32; @@ -1638,7 +1670,7 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc) * Cleanup any pending requests. */ static void -bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc) +bfa_ioc_mbox_flush(struct bfa_ioc *ioc) { struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; struct bfa_mbox_cmd *cmd; @@ -1650,17 +1682,11 @@ bfa_ioc_mbox_hbfail(struct bfa_ioc *ioc) static void bfa_ioc_fail_notify(struct bfa_ioc *ioc) { - struct list_head *qe; - struct bfa_ioc_hbfail_notify *notify; - /** * Notify driver and common modules registered for notification. */ ioc->cbfn->hbfail_cbfn(ioc->bfa); - list_for_each(qe, &ioc->hb_notify_q) { - notify = (struct bfa_ioc_hbfail_notify *) qe; - notify->cbfn(notify->cbarg); - } + bfa_ioc_event_notify(ioc, BFA_IOC_E_FAILED); } static void @@ -1684,7 +1710,7 @@ bfa_ioc_pf_initfailed(struct bfa_ioc *ioc) static void bfa_ioc_pf_failed(struct bfa_ioc *ioc) { - bfa_fsm_send_event(ioc, IOC_E_PFAILED); + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); } static void @@ -1839,7 +1865,7 @@ bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, struct bfa_ioc_cbfn *cbfn) ioc->iocpf.ioc = ioc; bfa_ioc_mbox_attach(ioc); - INIT_LIST_HEAD(&ioc->hb_notify_q); + INIT_LIST_HEAD(&ioc->notify_q); bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); bfa_fsm_send_event(ioc, IOC_E_RESET); @@ -1969,6 +1995,8 @@ bfa_nw_ioc_mbox_queue(struct bfa_ioc *ioc, struct bfa_mbox_cmd *cmd) * mailbox is free -- queue command to firmware */ bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); + + return; } /** @@ -2001,18 +2029,30 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc) void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc) { + bfa_ioc_stats(ioc, ioc_hbfails); + bfa_ioc_stats_hb_count(ioc, ioc->hb_count); bfa_fsm_send_event(ioc, IOC_E_HWERROR); } /** + * return true if IOC is disabled + */ +bool +bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc) +{ + return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) || + bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled); +} + +/** * Add to IOC heartbeat failure notification queue. To be used by common * modules such as cee, port, diag. */ void -bfa_nw_ioc_hbfail_register(struct bfa_ioc *ioc, - struct bfa_ioc_hbfail_notify *notify) +bfa_nw_ioc_notify_register(struct bfa_ioc *ioc, + struct bfa_ioc_notify *notify) { - list_add_tail(¬ify->qe, &ioc->hb_notify_q); + list_add_tail(¬ify->qe, &ioc->notify_q); } #define BFA_MFG_NAME "Brocade" @@ -2217,6 +2257,7 @@ bfa_ioc_recover(struct bfa_ioc *ioc) { pr_crit("Heart Beat of IOC has failed\n"); bfa_ioc_stats(ioc, ioc_hbfails); + bfa_ioc_stats_hb_count(ioc, ioc->hb_count); bfa_fsm_send_event(ioc, IOC_E_HBFAIL); } |