diff options
author | Krishna Gudipati <kgudipat@brocade.com> | 2010-12-13 19:17:11 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-12-21 13:37:15 -0500 |
commit | f1d584d70f31f54e0a559049906f42db89e2746d (patch) | |
tree | 7bfa223d53221c5930802b988a8bb6c0aed201d6 /drivers/scsi/bfa/bfa_ioc.c | |
parent | f3a060ca57903daaf2f1a88c6c25832619b2a74f (diff) |
[SCSI] bfa: IOC auto recovery fix.
- Made IOC auto_recovery synchronized and not timer based.
- Only one PCI function will attempt to recover and reinitialize
the ASIC on a failure, after all the active PCI fns
acknowledge the IOC failure.
Signed-off-by: Krishna Gudipati <kgudipat@brocade.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/bfa/bfa_ioc.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.c | 288 |
1 files changed, 212 insertions, 76 deletions
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 9173bf20ffba..05b0ff93284a 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
@@ -29,7 +29,7 @@ BFA_TRC_FILE(CNA, IOC); | |||
29 | #define BFA_IOC_TOV 3000 /* msecs */ | 29 | #define BFA_IOC_TOV 3000 /* msecs */ |
30 | #define BFA_IOC_HWSEM_TOV 500 /* msecs */ | 30 | #define BFA_IOC_HWSEM_TOV 500 /* msecs */ |
31 | #define BFA_IOC_HB_TOV 500 /* msecs */ | 31 | #define BFA_IOC_HB_TOV 500 /* msecs */ |
32 | #define BFA_IOC_HWINIT_MAX 2 | 32 | #define BFA_IOC_HWINIT_MAX 5 |
33 | #define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV | 33 | #define BFA_IOC_TOV_RECOVER BFA_IOC_HB_TOV |
34 | 34 | ||
35 | #define bfa_ioc_timer_start(__ioc) \ | 35 | #define bfa_ioc_timer_start(__ioc) \ |
@@ -54,17 +54,16 @@ BFA_TRC_FILE(CNA, IOC); | |||
54 | ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc)) | 54 | ((__ioc)->ioc_hwif->ioc_firmware_unlock(__ioc)) |
55 | #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc)) | 55 | #define bfa_ioc_reg_init(__ioc) ((__ioc)->ioc_hwif->ioc_reg_init(__ioc)) |
56 | #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) | 56 | #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) |
57 | #define bfa_ioc_notify_hbfail(__ioc) \ | 57 | #define bfa_ioc_notify_fail(__ioc) \ |
58 | ((__ioc)->ioc_hwif->ioc_notify_hbfail(__ioc)) | 58 | ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) |
59 | 59 | #define bfa_ioc_sync_join(__ioc) \ | |
60 | #ifdef BFA_IOC_IS_UEFI | 60 | ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) |
61 | #define bfa_ioc_is_bios_optrom(__ioc) (0) | 61 | #define bfa_ioc_sync_leave(__ioc) \ |
62 | #define bfa_ioc_is_uefi(__ioc) BFA_IOC_IS_UEFI | 62 | ((__ioc)->ioc_hwif->ioc_sync_leave(__ioc)) |
63 | #else | 63 | #define bfa_ioc_sync_ack(__ioc) \ |
64 | #define bfa_ioc_is_bios_optrom(__ioc) \ | 64 | ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc)) |
65 | (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(__ioc)) < BFA_IOC_FWIMG_MINSZ) | 65 | #define bfa_ioc_sync_complete(__ioc) \ |
66 | #define bfa_ioc_is_uefi(__ioc) (0) | 66 | ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc)) |
67 | #endif | ||
68 | 67 | ||
69 | #define bfa_ioc_mbox_cmd_pending(__ioc) \ | 68 | #define bfa_ioc_mbox_cmd_pending(__ioc) \ |
70 | (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ | 69 | (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ |
@@ -104,10 +103,11 @@ enum ioc_event { | |||
104 | IOC_E_ENABLED = 5, /* f/w enabled */ | 103 | IOC_E_ENABLED = 5, /* f/w enabled */ |
105 | IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ | 104 | IOC_E_FWRSP_GETATTR = 6, /* IOC get attribute response */ |
106 | IOC_E_DISABLED = 7, /* f/w disabled */ | 105 | IOC_E_DISABLED = 7, /* f/w disabled */ |
107 | IOC_E_PFFAILED = 8, /* failure notice by iocpf sm */ | 106 | IOC_E_INITFAILED = 8, /* failure notice by iocpf sm */ |
108 | IOC_E_HBFAIL = 9, /* heartbeat failure */ | 107 | IOC_E_PFFAILED = 9, /* failure notice by iocpf sm */ |
109 | IOC_E_HWERROR = 10, /* hardware error interrupt */ | 108 | IOC_E_HBFAIL = 10, /* heartbeat failure */ |
110 | IOC_E_TIMEOUT = 11, /* timeout */ | 109 | IOC_E_HWERROR = 11, /* hardware error interrupt */ |
110 | IOC_E_TIMEOUT = 12, /* timeout */ | ||
111 | }; | 111 | }; |
112 | 112 | ||
113 | bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event); | 113 | bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc_s, enum ioc_event); |
@@ -195,9 +195,14 @@ bfa_fsm_state_decl(bfa_iocpf, semwait, struct bfa_iocpf_s, enum iocpf_event); | |||
195 | bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event); | 195 | bfa_fsm_state_decl(bfa_iocpf, hwinit, struct bfa_iocpf_s, enum iocpf_event); |
196 | bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event); | 196 | bfa_fsm_state_decl(bfa_iocpf, enabling, struct bfa_iocpf_s, enum iocpf_event); |
197 | bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event); | 197 | bfa_fsm_state_decl(bfa_iocpf, ready, struct bfa_iocpf_s, enum iocpf_event); |
198 | bfa_fsm_state_decl(bfa_iocpf, initfail_sync, struct bfa_iocpf_s, | ||
199 | enum iocpf_event); | ||
198 | bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event); | 200 | bfa_fsm_state_decl(bfa_iocpf, initfail, struct bfa_iocpf_s, enum iocpf_event); |
201 | bfa_fsm_state_decl(bfa_iocpf, fail_sync, struct bfa_iocpf_s, enum iocpf_event); | ||
199 | bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event); | 202 | bfa_fsm_state_decl(bfa_iocpf, fail, struct bfa_iocpf_s, enum iocpf_event); |
200 | bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event); | 203 | bfa_fsm_state_decl(bfa_iocpf, disabling, struct bfa_iocpf_s, enum iocpf_event); |
204 | bfa_fsm_state_decl(bfa_iocpf, disabling_sync, struct bfa_iocpf_s, | ||
205 | enum iocpf_event); | ||
201 | bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event); | 206 | bfa_fsm_state_decl(bfa_iocpf, disabled, struct bfa_iocpf_s, enum iocpf_event); |
202 | 207 | ||
203 | static struct bfa_sm_table_s iocpf_sm_table[] = { | 208 | static struct bfa_sm_table_s iocpf_sm_table[] = { |
@@ -208,9 +213,12 @@ static struct bfa_sm_table_s iocpf_sm_table[] = { | |||
208 | {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT}, | 213 | {BFA_SM(bfa_iocpf_sm_hwinit), BFA_IOCPF_HWINIT}, |
209 | {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT}, | 214 | {BFA_SM(bfa_iocpf_sm_enabling), BFA_IOCPF_HWINIT}, |
210 | {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY}, | 215 | {BFA_SM(bfa_iocpf_sm_ready), BFA_IOCPF_READY}, |
216 | {BFA_SM(bfa_iocpf_sm_initfail_sync), BFA_IOCPF_INITFAIL}, | ||
211 | {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL}, | 217 | {BFA_SM(bfa_iocpf_sm_initfail), BFA_IOCPF_INITFAIL}, |
218 | {BFA_SM(bfa_iocpf_sm_fail_sync), BFA_IOCPF_FAIL}, | ||
212 | {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL}, | 219 | {BFA_SM(bfa_iocpf_sm_fail), BFA_IOCPF_FAIL}, |
213 | {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING}, | 220 | {BFA_SM(bfa_iocpf_sm_disabling), BFA_IOCPF_DISABLING}, |
221 | {BFA_SM(bfa_iocpf_sm_disabling_sync), BFA_IOCPF_DISABLING}, | ||
214 | {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED}, | 222 | {BFA_SM(bfa_iocpf_sm_disabled), BFA_IOCPF_DISABLED}, |
215 | }; | 223 | }; |
216 | 224 | ||
@@ -497,7 +505,7 @@ bfa_ioc_sm_fail_retry_entry(struct bfa_ioc_s *ioc) | |||
497 | } | 505 | } |
498 | 506 | ||
499 | /* | 507 | /* |
500 | * Hardware initialization failed. | 508 | * Hardware initialization retry. |
501 | */ | 509 | */ |
502 | static void | 510 | static void |
503 | bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) | 511 | bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) |
@@ -519,6 +527,10 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
519 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); | 527 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_INITFAIL); |
520 | break; | 528 | break; |
521 | 529 | ||
530 | case IOC_E_INITFAILED: | ||
531 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); | ||
532 | break; | ||
533 | |||
522 | case IOC_E_ENABLE: | 534 | case IOC_E_ENABLE: |
523 | break; | 535 | break; |
524 | 536 | ||
@@ -561,6 +573,11 @@ bfa_ioc_sm_fail(struct bfa_ioc_s *ioc, enum ioc_event event) | |||
561 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); | 573 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); |
562 | break; | 574 | break; |
563 | 575 | ||
576 | case IOC_E_DETACH: | ||
577 | bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); | ||
578 | bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_STOP); | ||
579 | break; | ||
580 | |||
564 | case IOC_E_HWERROR: | 581 | case IOC_E_HWERROR: |
565 | /* | 582 | /* |
566 | * HB failure notification, ignore. | 583 | * HB failure notification, ignore. |
@@ -630,8 +647,15 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
630 | switch (event) { | 647 | switch (event) { |
631 | case IOCPF_E_SEMLOCKED: | 648 | case IOCPF_E_SEMLOCKED: |
632 | if (bfa_ioc_firmware_lock(ioc)) { | 649 | if (bfa_ioc_firmware_lock(ioc)) { |
633 | iocpf->retry_count = 0; | 650 | if (bfa_ioc_sync_complete(ioc)) { |
634 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | 651 | iocpf->retry_count = 0; |
652 | bfa_ioc_sync_join(ioc); | ||
653 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | ||
654 | } else { | ||
655 | bfa_ioc_firmware_unlock(ioc); | ||
656 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
657 | bfa_sem_timer_start(ioc); | ||
658 | } | ||
635 | } else { | 659 | } else { |
636 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 660 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
637 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch); | 661 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_mismatch); |
@@ -722,13 +746,18 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
722 | 746 | ||
723 | switch (event) { | 747 | switch (event) { |
724 | case IOCPF_E_SEMLOCKED: | 748 | case IOCPF_E_SEMLOCKED: |
725 | iocpf->retry_count = 0; | 749 | if (bfa_ioc_sync_complete(ioc)) { |
726 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | 750 | bfa_ioc_sync_join(ioc); |
751 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | ||
752 | } else { | ||
753 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
754 | bfa_sem_timer_start(ioc); | ||
755 | } | ||
727 | break; | 756 | break; |
728 | 757 | ||
729 | case IOCPF_E_DISABLE: | 758 | case IOCPF_E_DISABLE: |
730 | bfa_sem_timer_stop(ioc); | 759 | bfa_sem_timer_stop(ioc); |
731 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | 760 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); |
732 | break; | 761 | break; |
733 | 762 | ||
734 | default: | 763 | default: |
@@ -767,23 +796,16 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
767 | */ | 796 | */ |
768 | 797 | ||
769 | case IOCPF_E_TIMEOUT: | 798 | case IOCPF_E_TIMEOUT: |
770 | iocpf->retry_count++; | ||
771 | if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { | ||
772 | bfa_iocpf_timer_start(ioc); | ||
773 | bfa_ioc_hwinit(ioc, BFA_TRUE); | ||
774 | break; | ||
775 | } | ||
776 | |||
777 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 799 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
778 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | ||
779 | |||
780 | if (event == IOCPF_E_TIMEOUT) | 800 | if (event == IOCPF_E_TIMEOUT) |
781 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); | 801 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); |
802 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); | ||
782 | break; | 803 | break; |
783 | 804 | ||
784 | case IOCPF_E_DISABLE: | 805 | case IOCPF_E_DISABLE: |
785 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
786 | bfa_iocpf_timer_stop(ioc); | 806 | bfa_iocpf_timer_stop(ioc); |
807 | bfa_ioc_sync_leave(ioc); | ||
808 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
787 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | 809 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); |
788 | break; | 810 | break; |
789 | 811 | ||
@@ -824,18 +846,10 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
824 | */ | 846 | */ |
825 | 847 | ||
826 | case IOCPF_E_TIMEOUT: | 848 | case IOCPF_E_TIMEOUT: |
827 | iocpf->retry_count++; | ||
828 | if (iocpf->retry_count < BFA_IOC_HWINIT_MAX) { | ||
829 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | ||
830 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | ||
831 | break; | ||
832 | } | ||
833 | |||
834 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 849 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
835 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | ||
836 | |||
837 | if (event == IOCPF_E_TIMEOUT) | 850 | if (event == IOCPF_E_TIMEOUT) |
838 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); | 851 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); |
852 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); | ||
839 | break; | 853 | break; |
840 | 854 | ||
841 | case IOCPF_E_DISABLE: | 855 | case IOCPF_E_DISABLE: |
@@ -872,20 +886,21 @@ bfa_iocpf_sm_ready(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
872 | break; | 886 | break; |
873 | 887 | ||
874 | case IOCPF_E_GETATTRFAIL: | 888 | case IOCPF_E_GETATTRFAIL: |
875 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | 889 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); |
876 | break; | 890 | break; |
877 | 891 | ||
878 | case IOCPF_E_FAIL: | 892 | case IOCPF_E_FAIL: |
879 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); | 893 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync); |
880 | break; | 894 | break; |
881 | 895 | ||
882 | case IOCPF_E_FWREADY: | 896 | case IOCPF_E_FWREADY: |
883 | if (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op)) | 897 | if (bfa_ioc_is_operational(ioc)) { |
884 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); | 898 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); |
885 | else | 899 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync); |
886 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | 900 | } else { |
887 | 901 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); | |
888 | bfa_fsm_send_event(ioc, IOC_E_PFFAILED); | 902 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); |
903 | } | ||
889 | break; | 904 | break; |
890 | 905 | ||
891 | default: | 906 | default: |
@@ -914,7 +929,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
914 | case IOCPF_E_FWRSP_DISABLE: | 929 | case IOCPF_E_FWRSP_DISABLE: |
915 | case IOCPF_E_FWREADY: | 930 | case IOCPF_E_FWREADY: |
916 | bfa_iocpf_timer_stop(ioc); | 931 | bfa_iocpf_timer_stop(ioc); |
917 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | 932 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); |
918 | break; | 933 | break; |
919 | 934 | ||
920 | case IOCPF_E_FAIL: | 935 | case IOCPF_E_FAIL: |
@@ -925,7 +940,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
925 | 940 | ||
926 | case IOCPF_E_TIMEOUT: | 941 | case IOCPF_E_TIMEOUT: |
927 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); | 942 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); |
928 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | 943 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); |
929 | break; | 944 | break; |
930 | 945 | ||
931 | case IOCPF_E_FWRSP_ENABLE: | 946 | case IOCPF_E_FWRSP_ENABLE: |
@@ -936,6 +951,37 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
936 | } | 951 | } |
937 | } | 952 | } |
938 | 953 | ||
954 | static void | ||
955 | bfa_iocpf_sm_disabling_sync_entry(struct bfa_iocpf_s *iocpf) | ||
956 | { | ||
957 | bfa_ioc_hw_sem_get(iocpf->ioc); | ||
958 | } | ||
959 | |||
960 | /** | ||
961 | * IOC hb ack request is being removed. | ||
962 | */ | ||
963 | static void | ||
964 | bfa_iocpf_sm_disabling_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | ||
965 | { | ||
966 | struct bfa_ioc_s *ioc = iocpf->ioc; | ||
967 | |||
968 | bfa_trc(ioc, event); | ||
969 | |||
970 | switch (event) { | ||
971 | case IOCPF_E_SEMLOCKED: | ||
972 | bfa_ioc_sync_leave(ioc); | ||
973 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
974 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | ||
975 | break; | ||
976 | |||
977 | case IOCPF_E_FAIL: | ||
978 | break; | ||
979 | |||
980 | default: | ||
981 | bfa_sm_fault(ioc, event); | ||
982 | } | ||
983 | } | ||
984 | |||
939 | /* | 985 | /* |
940 | * IOC disable completion entry. | 986 | * IOC disable completion entry. |
941 | */ | 987 | */ |
@@ -954,6 +1000,7 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
954 | 1000 | ||
955 | switch (event) { | 1001 | switch (event) { |
956 | case IOCPF_E_ENABLE: | 1002 | case IOCPF_E_ENABLE: |
1003 | iocpf->retry_count = 0; | ||
957 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); | 1004 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); |
958 | break; | 1005 | break; |
959 | 1006 | ||
@@ -968,9 +1015,64 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
968 | } | 1015 | } |
969 | 1016 | ||
970 | static void | 1017 | static void |
1018 | bfa_iocpf_sm_initfail_sync_entry(struct bfa_iocpf_s *iocpf) | ||
1019 | { | ||
1020 | bfa_ioc_hw_sem_get(iocpf->ioc); | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * @brief | ||
1025 | * Hardware initialization failed. | ||
1026 | */ | ||
1027 | static void | ||
1028 | bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | ||
1029 | { | ||
1030 | struct bfa_ioc_s *ioc = iocpf->ioc; | ||
1031 | |||
1032 | bfa_trc(ioc, event); | ||
1033 | |||
1034 | switch (event) { | ||
1035 | case IOCPF_E_SEMLOCKED: | ||
1036 | bfa_ioc_notify_fail(ioc); | ||
1037 | bfa_ioc_sync_ack(ioc); | ||
1038 | iocpf->retry_count++; | ||
1039 | if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) { | ||
1040 | bfa_ioc_sync_leave(ioc); | ||
1041 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
1042 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | ||
1043 | } else { | ||
1044 | if (bfa_ioc_sync_complete(ioc)) | ||
1045 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | ||
1046 | else { | ||
1047 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
1048 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); | ||
1049 | } | ||
1050 | } | ||
1051 | break; | ||
1052 | |||
1053 | case IOCPF_E_DISABLE: | ||
1054 | bfa_sem_timer_stop(ioc); | ||
1055 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); | ||
1056 | break; | ||
1057 | |||
1058 | case IOCPF_E_STOP: | ||
1059 | bfa_sem_timer_stop(ioc); | ||
1060 | bfa_ioc_firmware_unlock(ioc); | ||
1061 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); | ||
1062 | break; | ||
1063 | |||
1064 | case IOCPF_E_FAIL: | ||
1065 | break; | ||
1066 | |||
1067 | default: | ||
1068 | bfa_sm_fault(ioc, event); | ||
1069 | } | ||
1070 | } | ||
1071 | |||
1072 | static void | ||
971 | bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf) | 1073 | bfa_iocpf_sm_initfail_entry(struct bfa_iocpf_s *iocpf) |
972 | { | 1074 | { |
973 | bfa_iocpf_timer_start(iocpf->ioc); | 1075 | bfa_fsm_send_event(iocpf->ioc, IOC_E_INITFAILED); |
974 | } | 1076 | } |
975 | 1077 | ||
976 | /* | 1078 | /* |
@@ -985,46 +1087,77 @@ bfa_iocpf_sm_initfail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
985 | 1087 | ||
986 | switch (event) { | 1088 | switch (event) { |
987 | case IOCPF_E_DISABLE: | 1089 | case IOCPF_E_DISABLE: |
988 | bfa_iocpf_timer_stop(ioc); | ||
989 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | 1090 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); |
990 | break; | 1091 | break; |
991 | 1092 | ||
992 | case IOCPF_E_STOP: | 1093 | case IOCPF_E_STOP: |
993 | bfa_iocpf_timer_stop(ioc); | ||
994 | bfa_ioc_firmware_unlock(ioc); | 1094 | bfa_ioc_firmware_unlock(ioc); |
995 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); | 1095 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); |
996 | break; | 1096 | break; |
997 | 1097 | ||
998 | case IOCPF_E_TIMEOUT: | ||
999 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); | ||
1000 | break; | ||
1001 | |||
1002 | default: | 1098 | default: |
1003 | bfa_sm_fault(ioc, event); | 1099 | bfa_sm_fault(ioc, event); |
1004 | } | 1100 | } |
1005 | } | 1101 | } |
1006 | 1102 | ||
1007 | static void | 1103 | static void |
1008 | bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) | 1104 | bfa_iocpf_sm_fail_sync_entry(struct bfa_iocpf_s *iocpf) |
1009 | { | 1105 | { |
1010 | /* | 1106 | /** |
1011 | * Mark IOC as failed in hardware and stop firmware. | 1107 | * Mark IOC as failed in hardware and stop firmware. |
1012 | */ | 1108 | */ |
1013 | bfa_ioc_lpu_stop(iocpf->ioc); | 1109 | bfa_ioc_lpu_stop(iocpf->ioc); |
1014 | writel(BFI_IOC_FAIL, iocpf->ioc->ioc_regs.ioc_fwstate); | ||
1015 | |||
1016 | /* | ||
1017 | * Notify other functions on HB failure. | ||
1018 | */ | ||
1019 | bfa_ioc_notify_hbfail(iocpf->ioc); | ||
1020 | 1110 | ||
1021 | /* | 1111 | /** |
1022 | * Flush any queued up mailbox requests. | 1112 | * Flush any queued up mailbox requests. |
1023 | */ | 1113 | */ |
1024 | bfa_ioc_mbox_hbfail(iocpf->ioc); | 1114 | bfa_ioc_mbox_hbfail(iocpf->ioc); |
1025 | 1115 | ||
1026 | if (iocpf->auto_recover) | 1116 | bfa_ioc_hw_sem_get(iocpf->ioc); |
1027 | bfa_iocpf_recovery_timer_start(iocpf->ioc); | 1117 | } |
1118 | |||
1119 | static void | ||
1120 | bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | ||
1121 | { | ||
1122 | struct bfa_ioc_s *ioc = iocpf->ioc; | ||
1123 | |||
1124 | bfa_trc(ioc, event); | ||
1125 | |||
1126 | switch (event) { | ||
1127 | case IOCPF_E_SEMLOCKED: | ||
1128 | iocpf->retry_count = 0; | ||
1129 | bfa_ioc_sync_ack(ioc); | ||
1130 | bfa_ioc_notify_fail(ioc); | ||
1131 | if (!iocpf->auto_recover) { | ||
1132 | bfa_ioc_sync_leave(ioc); | ||
1133 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
1134 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); | ||
1135 | } else { | ||
1136 | if (bfa_ioc_sync_complete(ioc)) | ||
1137 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); | ||
1138 | else { | ||
1139 | writel(1, ioc->ioc_regs.ioc_sem_reg); | ||
1140 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); | ||
1141 | } | ||
1142 | } | ||
1143 | break; | ||
1144 | |||
1145 | case IOCPF_E_DISABLE: | ||
1146 | bfa_sem_timer_stop(ioc); | ||
1147 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); | ||
1148 | break; | ||
1149 | |||
1150 | case IOCPF_E_FAIL: | ||
1151 | break; | ||
1152 | |||
1153 | default: | ||
1154 | bfa_sm_fault(ioc, event); | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | static void | ||
1159 | bfa_iocpf_sm_fail_entry(struct bfa_iocpf_s *iocpf) | ||
1160 | { | ||
1028 | } | 1161 | } |
1029 | 1162 | ||
1030 | /* | 1163 | /* |
@@ -1039,15 +1172,9 @@ bfa_iocpf_sm_fail(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
1039 | 1172 | ||
1040 | switch (event) { | 1173 | switch (event) { |
1041 | case IOCPF_E_DISABLE: | 1174 | case IOCPF_E_DISABLE: |
1042 | if (iocpf->auto_recover) | ||
1043 | bfa_iocpf_timer_stop(ioc); | ||
1044 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); | 1175 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); |
1045 | break; | 1176 | break; |
1046 | 1177 | ||
1047 | case IOCPF_E_TIMEOUT: | ||
1048 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); | ||
1049 | break; | ||
1050 | |||
1051 | default: | 1178 | default: |
1052 | bfa_sm_fault(ioc, event); | 1179 | bfa_sm_fault(ioc, event); |
1053 | } | 1180 | } |
@@ -1438,7 +1565,6 @@ bfa_ioc_hb_check(void *cbarg) | |||
1438 | 1565 | ||
1439 | hb_count = readl(ioc->ioc_regs.heartbeat); | 1566 | hb_count = readl(ioc->ioc_regs.heartbeat); |
1440 | if (ioc->hb_count == hb_count) { | 1567 | if (ioc->hb_count == hb_count) { |
1441 | printk(KERN_CRIT "Firmware heartbeat failure at %d", hb_count); | ||
1442 | bfa_ioc_recover(ioc); | 1568 | bfa_ioc_recover(ioc); |
1443 | return; | 1569 | return; |
1444 | } else { | 1570 | } else { |
@@ -2153,6 +2279,16 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) | |||
2153 | return BFA_TRUE; | 2279 | return BFA_TRUE; |
2154 | } | 2280 | } |
2155 | 2281 | ||
2282 | /** | ||
2283 | * Reset IOC fwstate registers. | ||
2284 | */ | ||
2285 | void | ||
2286 | bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc) | ||
2287 | { | ||
2288 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | ||
2289 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); | ||
2290 | } | ||
2291 | |||
2156 | #define BFA_MFG_NAME "Brocade" | 2292 | #define BFA_MFG_NAME "Brocade" |
2157 | void | 2293 | void |
2158 | bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, | 2294 | bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, |