diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2010-12-13 19:16:09 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:37:11 -0500 |
commit | 4e78efefa3c083240bd47153ffa99642bfdc7811 (patch) | |
tree | 22fc66e5ce15626437555a5574ca93323e8355a8 /drivers/scsi | |
parent | da99dcc98dd66a2de4864645bcafffd93cf5a62f (diff) |
[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: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.c | 141 |
1 files changed, 74 insertions, 67 deletions
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c4d56506e966..9173bf20ffba 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
@@ -88,6 +88,8 @@ static void bfa_ioc_recover(struct bfa_ioc_s *ioc); | |||
88 | static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); | 88 | static void bfa_ioc_check_attr_wwns(struct bfa_ioc_s *ioc); |
89 | static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); | 89 | static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); |
90 | static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); | 90 | static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); |
91 | static void bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc); | ||
92 | static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc); | ||
91 | static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); | 93 | static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); |
92 | 94 | ||
93 | 95 | ||
@@ -102,7 +104,7 @@ enum ioc_event { | |||
102 | IOC_E_ENABLED = 5, /* f/w enabled */ | 104 | IOC_E_ENABLED = 5, /* f/w enabled */ |
103 | IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ | 105 | IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ |
104 | IOC_E_DISABLED = 7, /* f/w disabled */ | 106 | IOC_E_DISABLED = 7, /* f/w disabled */ |
105 | IOC_E_FAILED = 8, /* failure notice by iocpf sm */ | 107 | IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */ |
106 | IOC_E_HBFAIL = 9, /* heartbeat failure */ | 108 | IOC_E_HBFAIL = 9, /* heartbeat failure */ |
107 | IOC_E_HWERROR = 10, /* hardware error interrupt */ | 109 | IOC_E_HWERROR = 10, /* hardware error interrupt */ |
108 | IOC_E_TIMEOUT = 11, /* timeout */ | 110 | IOC_E_TIMEOUT = 11, /* timeout */ |
@@ -113,7 +115,7 @@ bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event); | |||
113 | bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event); | 115 | bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event); |
114 | bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event); | 116 | bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event); |
115 | bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event); | 117 | bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event); |
116 | bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event); | 118 | bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc_s, enum ioc_event); |
117 | bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event); | 119 | bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc_s, enum ioc_event); |
118 | bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event); | 120 | bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event); |
119 | bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event); | 121 | 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 | {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING}, | 126 | {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_ENABLING}, |
125 | {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR}, | 127 | {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR}, |
126 | {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, | 128 | {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, |
127 | {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL}, | 129 | {BFA_SM(bfa_ioc_sm_fail_retry), BFA_IOC_INITFAIL}, |
128 | {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL}, | 130 | {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL}, |
129 | {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, | 131 | {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, |
130 | {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, | 132 | {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 | bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); | 300 | bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); |
299 | break; | 301 | break; |
300 | 302 | ||
301 | case IOC_E_FAILED: | 303 | case IOC_E_PFFAILED: |
302 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | 304 | /* !!! fall through !!! */ |
303 | break; | ||
304 | |||
305 | case IOC_E_HWERROR: | 305 | case IOC_E_HWERROR: |
306 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | 306 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); |
307 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); | 307 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); |
308 | if (event != IOC_E_PFFAILED) | ||
309 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); | ||
308 | break; | 310 | break; |
309 | 311 | ||
310 | case IOC_E_DISABLE: | 312 | case IOC_E_DISABLE: |
@@ -347,18 +349,16 @@ bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
347 | bfa_fsm_set_state(ioc, bfa_ioc_sm_op); | 349 | bfa_fsm_set_state(ioc, bfa_ioc_sm_op); |
348 | break; | 350 | break; |
349 | 351 | ||
350 | case IOC_E_FAILED: | ||
351 | bfa_ioc_timer_stop(ioc); | ||
352 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | ||
353 | break; | 352 | break; |
354 | 353 | case IOC_E_PFFAILED: | |
355 | case IOC_E_HWERROR: | 354 | case IOC_E_HWERROR: |
356 | bfa_ioc_timer_stop(ioc); | 355 | bfa_ioc_timer_stop(ioc); |
357 | /* fall through */ | 356 | /* !!! fall through !!! */ |
358 | |||
359 | case IOC_E_TIMEOUT: | 357 | case IOC_E_TIMEOUT: |
360 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | 358 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); |
361 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); | 359 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); |
360 | if (event != IOC_E_PFFAILED) | ||
361 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_GETATTRFAIL); | ||
362 | break; | 362 | break; |
363 | 363 | ||
364 | case IOC_E_DISABLE: | 364 | case IOC_E_DISABLE: |
@@ -399,18 +399,20 @@ bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
399 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); | 399 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); |
400 | break; | 400 | break; |
401 | 401 | ||
402 | case IOC_E_FAILED: | 402 | case IOC_E_PFFAILED: |
403 | bfa_hb_timer_stop(ioc); | ||
404 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); | ||
405 | break; | ||
406 | |||
407 | case IOC_E_HWERROR: | 403 | case IOC_E_HWERROR: |
408 | bfa_hb_timer_stop(ioc); | 404 | bfa_hb_timer_stop(ioc); |
409 | /* !!! fall through !!! */ | 405 | /* !!! fall through !!! */ |
410 | |||
411 | case IOC_E_HBFAIL: | 406 | case IOC_E_HBFAIL: |
412 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); | 407 | bfa_ioc_fail_notify(ioc); |
413 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); | 408 | |
409 | if (ioc->iocpf.auto_recover) | ||
410 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); | ||
411 | else | ||
412 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); | ||
413 | |||
414 | if (event != IOC_E_PFFAILED) | ||
415 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FAIL); | ||
414 | break; | 416 | break; |
415 | 417 | ||
416 | default: | 418 | default: |
@@ -489,16 +491,16 @@ bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
489 | 491 | ||
490 | 492 | ||
491 | static void | 493 | static void |
492 | bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc) | 494 | bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc) |
493 | { | 495 | { |
494 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); | 496 | bfa_trc(ioc, 0); |
495 | } | 497 | } |
496 | 498 | ||
497 | /* | 499 | /* |
498 | * Hardware initialization failed. | 500 | * Hardware initialization failed. |
499 | */ | 501 | */ |
500 | static void | 502 | static void |
501 | bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) | 503 | bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) |
502 | { | 504 | { |
503 | bfa_trc(ioc, event); | 505 | bfa_trc(ioc, event); |
504 | 506 | ||
@@ -507,11 +509,17 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
507 | bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); | 509 | bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); |
508 | break; | 510 | break; |
509 | 511 | ||
510 | case IOC_E_FAILED: | 512 | case IOC_E_PFFAILED: |
513 | case IOC_E_HWERROR: | ||
511 | /* | 514 | /* |
512 | * Initialization failure during iocpf init retry. | 515 | * Initialization retry failed. |
513 | */ | 516 | */ |
514 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); | 517 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); |
518 | if (event != IOC_E_PFFAILED) | ||
519 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); | ||
520 | break; | ||
521 | |||
522 | case IOC_E_ENABLE: | ||
515 | break; | 523 | break; |
516 | 524 | ||
517 | case IOC_E_DISABLE: | 525 | case IOC_E_DISABLE: |
@@ -532,21 +540,7 @@ bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
532 | static void | 540 | static void |
533 | bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc) | 541 | bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc) |
534 | { | 542 | { |
535 | struct list_head *qe; | 543 | bfa_trc(ioc, 0); |
536 | struct bfa_ioc_hbfail_notify_s *notify; | ||
537 | struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; | ||
538 | |||
539 | /* | ||
540 | * Notify driver and common modules registered for notification. | ||
541 | */ | ||
542 | ioc->cbfn->hbfail_cbfn(ioc->bfa); | ||
543 | list_for_each(qe, &ioc->hb_notify_q) { | ||
544 | notify = (struct bfa_ioc_hbfail_notify_s *) qe; | ||
545 | notify->cbfn(notify->cbarg); | ||
546 | } | ||
547 | |||
548 | BFA_LOG(KERN_CRIT, bfad, bfa_log_level, | ||
549 | "Heart Beat of IOC has failed\n"); | ||
550 | } | 544 | } |
551 | 545 | ||
552 | /* | 546 | /* |
@@ -559,19 +553,10 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
559 | 553 | ||
560 | switch (event) { | 554 | switch (event) { |
561 | 555 | ||
562 | case IOC_E_FAILED: | ||
563 | /* | ||
564 | * Initialization failure during iocpf recovery. | ||
565 | * !!! Fall through !!! | ||
566 | */ | ||
567 | case IOC_E_ENABLE: | 556 | case IOC_E_ENABLE: |
568 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); | 557 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); |
569 | break; | 558 | break; |
570 | 559 | ||
571 | case IOC_E_ENABLED: | ||
572 | bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); | ||
573 | break; | ||
574 | |||
575 | case IOC_E_DISABLE: | 560 | case IOC_E_DISABLE: |
576 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); | 561 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); |
577 | break; | 562 | break; |
@@ -793,7 +778,7 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
793 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | 778 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); |
794 | 779 | ||
795 | if (event == IOCPF_E_TIMEOUT) | 780 | if (event == IOCPF_E_TIMEOUT) |
796 | bfa_fsm_send_event(ioc, IOC_E_FAILED); | 781 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); |
797 | break; | 782 | break; |
798 | 783 | ||
799 | case IOCPF_E_DISABLE: | 784 | case IOCPF_E_DISABLE: |
@@ -850,7 +835,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
850 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | 835 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); |
851 | 836 | ||
852 | if (event == IOCPF_E_TIMEOUT) | 837 | if (event == IOCPF_E_TIMEOUT) |
853 | bfa_fsm_send_event(ioc, IOC_E_FAILED); | 838 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); |
854 | break; | 839 | break; |
855 | 840 | ||
856 | case IOCPF_E_DISABLE: | 841 | case IOCPF_E_DISABLE: |
@@ -900,7 +885,7 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
900 | else | 885 | else |
901 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | 886 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); |
902 | 887 | ||
903 | bfa_fsm_send_event(ioc, IOC_E_FAILED); | 888 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); |
904 | break; | 889 | break; |
905 | 890 | ||
906 | default: | 891 | default: |
@@ -1725,6 +1710,29 @@ bfa_ioc_smem_clr(struct bfa_ioc_s *ioc, u32 soff, u32 sz) | |||
1725 | } | 1710 | } |
1726 | 1711 | ||
1727 | static void | 1712 | static void |
1713 | bfa_ioc_fail_notify(struct bfa_ioc_s *ioc) | ||
1714 | { | ||
1715 | struct list_head *qe; | ||
1716 | struct bfa_ioc_hbfail_notify_s *notify; | ||
1717 | struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; | ||
1718 | |||
1719 | /** | ||
1720 | * Notify driver and common modules registered for notification. | ||
1721 | */ | ||
1722 | ioc->cbfn->hbfail_cbfn(ioc->bfa); | ||
1723 | list_for_each(qe, &ioc->hb_notify_q) { | ||
1724 | notify = (struct bfa_ioc_hbfail_notify_s *) qe; | ||
1725 | notify->cbfn(notify->cbarg); | ||
1726 | } | ||
1727 | |||
1728 | bfa_ioc_debug_save_ftrc(ioc); | ||
1729 | |||
1730 | BFA_LOG(KERN_CRIT, bfad, bfa_log_level, | ||
1731 | "Heart Beat of IOC has failed\n"); | ||
1732 | |||
1733 | } | ||
1734 | |||
1735 | static void | ||
1728 | bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) | 1736 | bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc) |
1729 | { | 1737 | { |
1730 | struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; | 1738 | struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad; |
@@ -2187,7 +2195,8 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, | |||
2187 | bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); | 2195 | bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); |
2188 | 2196 | ||
2189 | ad_attr->cna_capable = ioc->cna; | 2197 | ad_attr->cna_capable = ioc->cna; |
2190 | ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; | 2198 | ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna && |
2199 | !ad_attr->is_mezz; | ||
2191 | } | 2200 | } |
2192 | 2201 | ||
2193 | enum bfa_ioc_type_e | 2202 | enum bfa_ioc_type_e |
@@ -2530,13 +2539,16 @@ bfa_ioc_fw_stats_clear(struct bfa_ioc_s *ioc) | |||
2530 | * Save firmware trace if configured. | 2539 | * Save firmware trace if configured. |
2531 | */ | 2540 | */ |
2532 | static void | 2541 | static void |
2533 | bfa_ioc_debug_save(struct bfa_ioc_s *ioc) | 2542 | bfa_ioc_debug_save_ftrc(struct bfa_ioc_s *ioc) |
2534 | { | 2543 | { |
2535 | int tlen; | 2544 | int tlen; |
2536 | 2545 | ||
2537 | if (ioc->dbg_fwsave_len) { | 2546 | if (ioc->dbg_fwsave_once) { |
2538 | tlen = ioc->dbg_fwsave_len; | 2547 | ioc->dbg_fwsave_once = BFA_FALSE; |
2539 | bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); | 2548 | if (ioc->dbg_fwsave_len) { |
2549 | tlen = ioc->dbg_fwsave_len; | ||
2550 | bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); | ||
2551 | } | ||
2540 | } | 2552 | } |
2541 | } | 2553 | } |
2542 | 2554 | ||
@@ -2546,11 +2558,6 @@ bfa_ioc_debug_save(struct bfa_ioc_s *ioc) | |||
2546 | static void | 2558 | static void |
2547 | bfa_ioc_recover(struct bfa_ioc_s *ioc) | 2559 | bfa_ioc_recover(struct bfa_ioc_s *ioc) |
2548 | { | 2560 | { |
2549 | if (ioc->dbg_fwsave_once) { | ||
2550 | ioc->dbg_fwsave_once = BFA_FALSE; | ||
2551 | bfa_ioc_debug_save(ioc); | ||
2552 | } | ||
2553 | |||
2554 | bfa_ioc_stats(ioc, ioc_hbfails); | 2561 | bfa_ioc_stats(ioc, ioc_hbfails); |
2555 | bfa_fsm_send_event(ioc, IOC_E_HBFAIL); | 2562 | bfa_fsm_send_event(ioc, IOC_E_HBFAIL); |
2556 | } | 2563 | } |