diff options
author | Vijaya Mohan Guvva <vmohan@brocade.com> | 2013-05-13 05:33:26 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-06-26 16:12:19 -0400 |
commit | c679b599afa5dd38d20e058aa68bc94c1c1416a1 (patch) | |
tree | 605da11cd1b832a1254ba81ba6934482c87065df /drivers/scsi/bfa/bfa_ioc.c | |
parent | f2a0cc3ffd5ee123086b8e76522a85a937d89878 (diff) |
[SCSI] bfa: kdump fix on 815 and 825 adapters
Root cause: When kernel crashes, On brocade 815/825 adapters,
bfa IOC state machine and FW doesn't get a notification and
hence are not cleanly shutdown. So registers holding driver/IOC
state information are not reset back to valid disabled/parking
values. This causes subsequent driver initialization to fail
during kdump kernel boot.
Fix description: during the initialization of first PCI function, reset
corresponding register when unclean shutown is detect by reading chip
registers. This will make sure that ioc/fw gets clean re-initialization.
Signed-off-by: Vijaya Mohan Guvva <vmohan@brocade.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bfa/bfa_ioc.c')
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 0116c1032e25..8928b68551c3 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
@@ -67,6 +67,14 @@ BFA_TRC_FILE(CNA, IOC); | |||
67 | ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc)) | 67 | ((__ioc)->ioc_hwif->ioc_sync_ack(__ioc)) |
68 | #define bfa_ioc_sync_complete(__ioc) \ | 68 | #define bfa_ioc_sync_complete(__ioc) \ |
69 | ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc)) | 69 | ((__ioc)->ioc_hwif->ioc_sync_complete(__ioc)) |
70 | #define bfa_ioc_set_cur_ioc_fwstate(__ioc, __fwstate) \ | ||
71 | ((__ioc)->ioc_hwif->ioc_set_fwstate(__ioc, __fwstate)) | ||
72 | #define bfa_ioc_get_cur_ioc_fwstate(__ioc) \ | ||
73 | ((__ioc)->ioc_hwif->ioc_get_fwstate(__ioc)) | ||
74 | #define bfa_ioc_set_alt_ioc_fwstate(__ioc, __fwstate) \ | ||
75 | ((__ioc)->ioc_hwif->ioc_set_alt_fwstate(__ioc, __fwstate)) | ||
76 | #define bfa_ioc_get_alt_ioc_fwstate(__ioc) \ | ||
77 | ((__ioc)->ioc_hwif->ioc_get_alt_fwstate(__ioc)) | ||
70 | 78 | ||
71 | #define bfa_ioc_mbox_cmd_pending(__ioc) \ | 79 | #define bfa_ioc_mbox_cmd_pending(__ioc) \ |
72 | (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ | 80 | (!list_empty(&((__ioc)->mbox_mod.cmd_q)) || \ |
@@ -698,7 +706,7 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) | |||
698 | } | 706 | } |
699 | 707 | ||
700 | /* h/w sem init */ | 708 | /* h/w sem init */ |
701 | fwstate = readl(iocpf->ioc->ioc_regs.ioc_fwstate); | 709 | fwstate = bfa_ioc_get_cur_ioc_fwstate(iocpf->ioc); |
702 | if (fwstate == BFI_IOC_UNINIT) { | 710 | if (fwstate == BFI_IOC_UNINIT) { |
703 | writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg); | 711 | writel(1, iocpf->ioc->ioc_regs.ioc_init_sem_reg); |
704 | goto sem_get; | 712 | goto sem_get; |
@@ -725,8 +733,8 @@ bfa_iocpf_sm_fwcheck_entry(struct bfa_iocpf_s *iocpf) | |||
725 | 733 | ||
726 | bfa_trc(iocpf->ioc, fwstate); | 734 | bfa_trc(iocpf->ioc, fwstate); |
727 | bfa_trc(iocpf->ioc, swab32(fwhdr.exec)); | 735 | bfa_trc(iocpf->ioc, swab32(fwhdr.exec)); |
728 | writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.ioc_fwstate); | 736 | bfa_ioc_set_cur_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT); |
729 | writel(BFI_IOC_UNINIT, iocpf->ioc->ioc_regs.alt_ioc_fwstate); | 737 | bfa_ioc_set_alt_ioc_fwstate(iocpf->ioc, BFI_IOC_UNINIT); |
730 | 738 | ||
731 | /* | 739 | /* |
732 | * Unlock the hw semaphore. Should be here only once per boot. | 740 | * Unlock the hw semaphore. Should be here only once per boot. |
@@ -1037,7 +1045,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
1037 | */ | 1045 | */ |
1038 | 1046 | ||
1039 | case IOCPF_E_TIMEOUT: | 1047 | case IOCPF_E_TIMEOUT: |
1040 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); | 1048 | bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); |
1041 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); | 1049 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); |
1042 | break; | 1050 | break; |
1043 | 1051 | ||
@@ -1138,7 +1146,7 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
1138 | case IOCPF_E_SEMLOCKED: | 1146 | case IOCPF_E_SEMLOCKED: |
1139 | bfa_ioc_notify_fail(ioc); | 1147 | bfa_ioc_notify_fail(ioc); |
1140 | bfa_ioc_sync_leave(ioc); | 1148 | bfa_ioc_sync_leave(ioc); |
1141 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); | 1149 | bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); |
1142 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 1150 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
1143 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); | 1151 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); |
1144 | break; | 1152 | break; |
@@ -1227,7 +1235,7 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf_s *iocpf, enum iocpf_event event) | |||
1227 | bfa_ioc_notify_fail(ioc); | 1235 | bfa_ioc_notify_fail(ioc); |
1228 | if (!iocpf->auto_recover) { | 1236 | if (!iocpf->auto_recover) { |
1229 | bfa_ioc_sync_leave(ioc); | 1237 | bfa_ioc_sync_leave(ioc); |
1230 | writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); | 1238 | bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); |
1231 | writel(1, ioc->ioc_regs.ioc_sem_reg); | 1239 | writel(1, ioc->ioc_regs.ioc_sem_reg); |
1232 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); | 1240 | bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); |
1233 | } else { | 1241 | } else { |
@@ -1519,7 +1527,7 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) | |||
1519 | u32 boot_type; | 1527 | u32 boot_type; |
1520 | u32 boot_env; | 1528 | u32 boot_env; |
1521 | 1529 | ||
1522 | ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); | 1530 | ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc); |
1523 | 1531 | ||
1524 | if (force) | 1532 | if (force) |
1525 | ioc_fwstate = BFI_IOC_UNINIT; | 1533 | ioc_fwstate = BFI_IOC_UNINIT; |
@@ -2006,11 +2014,11 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env) | |||
2006 | * Initialize IOC state of all functions on a chip reset. | 2014 | * Initialize IOC state of all functions on a chip reset. |
2007 | */ | 2015 | */ |
2008 | if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) { | 2016 | if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) { |
2009 | writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate); | 2017 | bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_MEMTEST); |
2010 | writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate); | 2018 | bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_MEMTEST); |
2011 | } else { | 2019 | } else { |
2012 | writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate); | 2020 | bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_INITING); |
2013 | writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate); | 2021 | bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_INITING); |
2014 | } | 2022 | } |
2015 | 2023 | ||
2016 | bfa_ioc_msgflush(ioc); | 2024 | bfa_ioc_msgflush(ioc); |
@@ -2038,7 +2046,7 @@ bfa_ioc_is_operational(struct bfa_ioc_s *ioc) | |||
2038 | bfa_boolean_t | 2046 | bfa_boolean_t |
2039 | bfa_ioc_is_initialized(struct bfa_ioc_s *ioc) | 2047 | bfa_ioc_is_initialized(struct bfa_ioc_s *ioc) |
2040 | { | 2048 | { |
2041 | u32 r32 = readl(ioc->ioc_regs.ioc_fwstate); | 2049 | u32 r32 = bfa_ioc_get_cur_ioc_fwstate(ioc); |
2042 | 2050 | ||
2043 | return ((r32 != BFI_IOC_UNINIT) && | 2051 | return ((r32 != BFI_IOC_UNINIT) && |
2044 | (r32 != BFI_IOC_INITING) && | 2052 | (r32 != BFI_IOC_INITING) && |
@@ -2430,12 +2438,12 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) | |||
2430 | if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)) | 2438 | if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)) |
2431 | return BFA_FALSE; | 2439 | return BFA_FALSE; |
2432 | 2440 | ||
2433 | ioc_state = readl(ioc->ioc_regs.ioc_fwstate); | 2441 | ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc); |
2434 | if (!bfa_ioc_state_disabled(ioc_state)) | 2442 | if (!bfa_ioc_state_disabled(ioc_state)) |
2435 | return BFA_FALSE; | 2443 | return BFA_FALSE; |
2436 | 2444 | ||
2437 | if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) { | 2445 | if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_FC_8G1P) { |
2438 | ioc_state = readl(ioc->ioc_regs.alt_ioc_fwstate); | 2446 | ioc_state = bfa_ioc_get_cur_ioc_fwstate(ioc); |
2439 | if (!bfa_ioc_state_disabled(ioc_state)) | 2447 | if (!bfa_ioc_state_disabled(ioc_state)) |
2440 | return BFA_FALSE; | 2448 | return BFA_FALSE; |
2441 | } | 2449 | } |
@@ -2449,8 +2457,8 @@ bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) | |||
2449 | void | 2457 | void |
2450 | bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc) | 2458 | bfa_ioc_reset_fwstate(struct bfa_ioc_s *ioc) |
2451 | { | 2459 | { |
2452 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); | 2460 | bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_UNINIT); |
2453 | writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); | 2461 | bfa_ioc_set_alt_ioc_fwstate(ioc, BFI_IOC_UNINIT); |
2454 | } | 2462 | } |
2455 | 2463 | ||
2456 | #define BFA_MFG_NAME "Brocade" | 2464 | #define BFA_MFG_NAME "Brocade" |
@@ -2917,7 +2925,7 @@ bfa_iocpf_sem_timeout(void *ioc_arg) | |||
2917 | static void | 2925 | static void |
2918 | bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc) | 2926 | bfa_ioc_poll_fwinit(struct bfa_ioc_s *ioc) |
2919 | { | 2927 | { |
2920 | u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate); | 2928 | u32 fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc); |
2921 | 2929 | ||
2922 | bfa_trc(ioc, fwstate); | 2930 | bfa_trc(ioc, fwstate); |
2923 | 2931 | ||