diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index c1f72c49196f64e6f3e1498ca88802fb68754c23..6c7e0339dda44d0d7029cd83bd2700950e1c49d2 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -56,6 +56,8 @@ BFA_TRC_FILE(CNA, IOC); #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc)) #define bfa_ioc_notify_fail(__ioc) \ ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc)) +#define bfa_ioc_sync_start(__ioc) \ + ((__ioc)->ioc_hwif->ioc_sync_start(__ioc)) #define bfa_ioc_sync_join(__ioc) \ ((__ioc)->ioc_hwif->ioc_sync_join(__ioc)) #define bfa_ioc_sync_leave(__ioc) \ @@ -647,7 +649,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf_s *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_SEMLOCKED: if (bfa_ioc_firmware_lock(ioc)) { - if (bfa_ioc_sync_complete(ioc)) { + if (bfa_ioc_sync_start(ioc)) { iocpf->retry_count = 0; bfa_ioc_sync_join(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index ec9cf08b0e7f57696e183689b2c6defb6b6808e2..c85182a704fb5d8adaebc6e11b2d0279c8fd0c0e 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -263,6 +263,7 @@ struct bfa_ioc_hwif_s { bfa_boolean_t msix); void (*ioc_notify_fail) (struct bfa_ioc_s *ioc); void (*ioc_ownership_reset) (struct bfa_ioc_s *ioc); + bfa_boolean_t (*ioc_sync_start) (struct bfa_ioc_s *ioc); void (*ioc_sync_join) (struct bfa_ioc_s *ioc); void (*ioc_sync_leave) (struct bfa_ioc_s *ioc); void (*ioc_sync_ack) (struct bfa_ioc_s *ioc); diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c index e4a0713185b6747838be59357ceff512ea94c6ef..89ae4c8f95a2bc9506f7cf902b28a331f69b0bfa 100644 --- a/drivers/scsi/bfa/bfa_ioc_cb.c +++ b/drivers/scsi/bfa/bfa_ioc_cb.c @@ -32,6 +32,7 @@ static void bfa_ioc_cb_map_port(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); static void bfa_ioc_cb_notify_fail(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_ownership_reset(struct bfa_ioc_s *ioc); +static bfa_boolean_t bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_sync_join(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_sync_leave(struct bfa_ioc_s *ioc); static void bfa_ioc_cb_sync_ack(struct bfa_ioc_s *ioc); @@ -53,6 +54,7 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc) hwif_cb.ioc_isr_mode_set = bfa_ioc_cb_isr_mode_set; hwif_cb.ioc_notify_fail = bfa_ioc_cb_notify_fail; hwif_cb.ioc_ownership_reset = bfa_ioc_cb_ownership_reset; + hwif_cb.ioc_sync_start = bfa_ioc_cb_sync_start; hwif_cb.ioc_sync_join = bfa_ioc_cb_sync_join; hwif_cb.ioc_sync_leave = bfa_ioc_cb_sync_leave; hwif_cb.ioc_sync_ack = bfa_ioc_cb_sync_ack; @@ -194,6 +196,15 @@ bfa_ioc_cb_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) { } +/* + * Synchronized IOC failure processing routines + */ +static bfa_boolean_t +bfa_ioc_cb_sync_start(struct bfa_ioc_s *ioc) +{ + return bfa_ioc_cb_sync_complete(ioc); +} + /* * Cleanup hw semaphore and usecnt registers */ diff --git a/drivers/scsi/bfa/bfa_ioc_ct.c b/drivers/scsi/bfa/bfa_ioc_ct.c index 008d129ddfcd9d9d59a84b410d5a26596e9decf6..93612520f0d2bf3ca1810f3c9a48d93016484098 100644 --- a/drivers/scsi/bfa/bfa_ioc_ct.c +++ b/drivers/scsi/bfa/bfa_ioc_ct.c @@ -41,6 +41,7 @@ static void bfa_ioc_ct_map_port(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix); static void bfa_ioc_ct_notify_fail(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc); +static bfa_boolean_t bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_sync_join(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_sync_leave(struct bfa_ioc_s *ioc); static void bfa_ioc_ct_sync_ack(struct bfa_ioc_s *ioc); @@ -62,6 +63,7 @@ bfa_ioc_set_ct_hwif(struct bfa_ioc_s *ioc) hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set; hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail; hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset; + hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start; hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join; hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave; hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack; @@ -351,6 +353,30 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc_s *ioc) writel(1, ioc->ioc_regs.ioc_sem_reg); } +static bfa_boolean_t +bfa_ioc_ct_sync_start(struct bfa_ioc_s *ioc) +{ + uint32_t r32 = readl(ioc->ioc_regs.ioc_fail_sync); + uint32_t sync_reqd = bfa_ioc_ct_get_sync_reqd(r32); + + /* + * Driver load time. If the sync required bit for this PCI fn + * is set, it is due to an unclean exit by the driver for this + * PCI fn in the previous incarnation. Whoever comes here first + * should clean it up, no matter which PCI fn. + */ + + if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) { + writel(0, ioc->ioc_regs.ioc_fail_sync); + writel(1, ioc->ioc_regs.ioc_usage_reg); + writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate); + writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate); + return BFA_TRUE; + } + + return bfa_ioc_ct_sync_complete(ioc); +} + /* * Synchronized IOC failure processing routines */