Commit 4e78efef authored by Krishna Gudipati's avatar Krishna Gudipati Committed by James Bottomley

[SCSI] bfa: IOC fwtrace save logic & state machine fixes.

- Move fw trace save logic to bfa_ioc_sm_fail_entry(),
  so that fw trace is saved irrespective of the cause of the failure.
- Make bfa_ioc_sm_fail() a failure parking state.
- Rename bfa_ioc_sm_initfail() to a more appropriate bfa_ioc_sm_fail_retry()
  as it is no longer a parking state.
Signed-off-by: default avatarKrishna Gudipati <kgudipat@brocade.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent da99dcc9
...@@ -88,6 +88,8 @@ static void bfa_ioc_recover(struct bfa_ioc_s *ioc); ...@@ -88,6 +88,8 @@ static void bfa_ioc_recover(struct bfa_ioc_s *ioc);
static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc);
static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc);
static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
...@@ -102,7 +104,7 @@ enum ioc_event { ...@@ -102,7 +104,7 @@ enum ioc_event {
IOC_E_ENABLED = 5, /* f/w enabled */ IOC_E_ENABLED = 5, /* f/w enabled */
IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */
IOC_E_DISABLED = 7, /* f/w disabled */ IOC_E_DISABLED = 7, /* f/w disabled */
IOC_E_FAILED = 8, /* failure notice by iocpf sm */ IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */
IOC_E_HBFAIL = 9, /* heartbeat failure */ IOC_E_HBFAIL = 9, /* heartbeat failure */
IOC_E_HWERROR = 10, /* hardware error interrupt */ IOC_E_HWERROR = 10, /* hardware error interrupt */
IOC_E_TIMEOUT = 11, /* timeout */ IOC_E_TIMEOUT = 11, /* timeout */
...@@ -113,7 +115,7 @@ bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event); ...@@ -113,7 +115,7 @@ bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event);
bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event);
...@@ -124,7 +126,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = { ...@@ -124,7 +126,7 @@ static struct bfa_sm_table_s ioc_sm_table[] = {
{BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING}, {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING},
{BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR}, {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR},
{BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL},
{BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL}, {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL},
{BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL}, {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL},
{BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING},
{BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED},
...@@ -298,13 +300,13 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -298,13 +300,13 @@ bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break; break;
case IOC_E_FAILED: case IOC_E_PFFAILED:
bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); /* !!! fall through !!! */
break;
case IOC_E_HWERROR: case IOC_E_HWERROR:
bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
if (event != IOC_E_PFFAILED)
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
break; break;
case IOC_E_DISABLE: case IOC_E_DISABLE:
...@@ -347,18 +349,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -347,18 +349,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_op); bfa_fsm_set_state(ioc, bfa_ioc_sm_op);
break; break;
case IOC_E_FAILED:
bfa_ioc_timer_stop(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail);
break; break;
case IOC_E_PFFAILED:
case IOC_E_HWERROR: case IOC_E_HWERROR:
bfa_ioc_timer_stop(ioc); bfa_ioc_timer_stop(ioc);
/* fall through */ /* !!! fall through !!! */
case IOC_E_TIMEOUT: case IOC_E_TIMEOUT:
bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
if (event != IOC_E_PFFAILED)
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL);
break; break;
case IOC_E_DISABLE: case IOC_E_DISABLE:
...@@ -399,18 +399,20 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -399,18 +399,20 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break; break;
case IOC_E_FAILED: case IOC_E_PFFAILED:
bfa_hb_timer_stop(ioc);
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
break;
case IOC_E_HWERROR: case IOC_E_HWERROR:
bfa_hb_timer_stop(ioc); bfa_hb_timer_stop(ioc);
/* !!! fall through !!! */ /* !!! fall through !!! */
case IOC_E_HBFAIL: case IOC_E_HBFAIL:
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); bfa_ioc_fail_notify(ioc);
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
if (ioc->iocpf.auto_recover)
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry);
else
bfa_fsm_set_state(ioc, bfa_ioc_sm_fail);
if (event != IOC_E_PFFAILED)
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL);
break; break;
default: default:
...@@ -489,16 +491,16 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -489,16 +491,16 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event)
static void static void
bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc) bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc)
{ {
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); bfa_trc(ioc, 0);
} }
/* /*
* Hardware initialization failed. * Hardware initialization failed.
*/ */
static void static void
bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event)
{ {
bfa_trc(ioc, event); bfa_trc(ioc, event);
...@@ -507,11 +509,17 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -507,11 +509,17 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break; break;
case IOC_E_FAILED: case IOC_E_PFFAILED:
case IOC_E_HWERROR:
/* /*
* Initialization failure during iocpf init retry. * Initialization retry failed.
*/ */
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
if (event != IOC_E_PFFAILED)
bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL);
break;
case IOC_E_ENABLE:
break; break;
case IOC_E_DISABLE: case IOC_E_DISABLE:
...@@ -532,21 +540,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -532,21 +540,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event)
static void static void
bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc) bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
{ {
struct list_head *qe; bfa_trc(ioc, 0);
struct bfa_ioc_hbfail_notify_s *notify;
struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
/*
* 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_s *) qe;
notify->cbfn(notify->cbarg);
}
BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
"Heart Beat of IOC has failed\n");
} }
/* /*
...@@ -559,19 +553,10 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event) ...@@ -559,19 +553,10 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event)
switch (event) { switch (event) {
case IOC_E_FAILED:
/*
* Initialization failure during iocpf recovery.
* !!! Fall through !!!
*/
case IOC_E_ENABLE: case IOC_E_ENABLE:
ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
break; break;
case IOC_E_ENABLED:
bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr);
break;
case IOC_E_DISABLE: case IOC_E_DISABLE:
bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling);
break; break;
...@@ -793,7 +778,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) ...@@ -793,7 +778,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
if (event == IOCPF_E_TIMEOUT) if (event == IOCPF_E_TIMEOUT)
bfa_fsm_send_event(ioc, IOC_E_FAILED); bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
break; break;
case IOCPF_E_DISABLE: case IOCPF_E_DISABLE:
...@@ -850,7 +835,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) ...@@ -850,7 +835,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
if (event == IOCPF_E_TIMEOUT) if (event == IOCPF_E_TIMEOUT)
bfa_fsm_send_event(ioc, IOC_E_FAILED); bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
break; break;
case IOCPF_E_DISABLE: case IOCPF_E_DISABLE:
...@@ -900,7 +885,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) ...@@ -900,7 +885,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event)
else else
bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail);
bfa_fsm_send_event(ioc, IOC_E_FAILED); bfa_fsm_send_event(ioc, IOC_E_PFFAILED);
break; break;
default: default:
...@@ -1724,6 +1709,29 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz) ...@@ -1724,6 +1709,29 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz)
return BFA_STATUS_OK; return BFA_STATUS_OK;
} }
static void
bfa_ioc_fail_notify(struct bfa_ioc_s *ioc)
{
struct list_head *qe;
struct bfa_ioc_hbfail_notify_s *notify;
struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
/**
* 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_s *) qe;
notify->cbfn(notify->cbarg);
}
bfa_ioc_debug_save_ftrc(ioc);
BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
"Heart Beat of IOC has failed\n");
}
static void static void
bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
{ {
...@@ -2187,7 +2195,8 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, ...@@ -2187,7 +2195,8 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc,
bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver);
ad_attr->cna_capable = ioc->cna; ad_attr->cna_capable = ioc->cna;
ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna &&
!ad_attr->is_mezz;
} }
enum bfa_ioc_type_e enum bfa_ioc_type_e
...@@ -2530,13 +2539,16 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc) ...@@ -2530,13 +2539,16 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc)
* Save firmware trace if configured. * Save firmware trace if configured.
*/ */
static void static void
bfa_ioc_debug_save(struct bfa_ioc_s *ioc) bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc)
{ {
int tlen; int tlen;
if (ioc->dbg_fwsave_len) { if (ioc->dbg_fwsave_once) {
tlen = ioc->dbg_fwsave_len; ioc->dbg_fwsave_once = BFA_FALSE;
bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); if (ioc->dbg_fwsave_len) {
tlen = ioc->dbg_fwsave_len;
bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen);
}
} }
} }
...@@ -2546,11 +2558,6 @@ bfa_ioc_debug_save(struct bfa_ioc_s *ioc) ...@@ -2546,11 +2558,6 @@ bfa_ioc_debug_save(struct bfa_ioc_s *ioc)
static void static void
bfa_ioc_recover(struct bfa_ioc_s *ioc) bfa_ioc_recover(struct bfa_ioc_s *ioc)
{ {
if (ioc->dbg_fwsave_once) {
ioc->dbg_fwsave_once = BFA_FALSE;
bfa_ioc_debug_save(ioc);
}
bfa_ioc_stats(ioc, ioc_hbfails); bfa_ioc_stats(ioc, ioc_hbfails);
bfa_fsm_send_event(ioc, IOC_E_HBFAIL); bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment