aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorLalit Chandivade <lalit.chandivade@qlogic.com>2010-09-03 18:20:50 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-09-05 14:33:07 -0400
commita5b36321918b3a1295748b77c62976c167233eec (patch)
treed0e89c61324f72deca2ee2f60d61912eb6e51a59 /drivers/scsi/qla2xxx
parent6dbdda4d596f201b8a82a276a0c0b50ef2b899e8 (diff)
[SCSI] qla2xxx: Added AER support for ISP82xx.
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c134
3 files changed, 138 insertions, 5 deletions
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 1a1b281cea33..4edfc731ea96 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -511,6 +511,7 @@ extern void qla82xx_reset_chip(struct scsi_qla_host *);
511extern void qla82xx_config_rings(struct scsi_qla_host *); 511extern void qla82xx_config_rings(struct scsi_qla_host *);
512extern int qla82xx_pinit_from_rom(scsi_qla_host_t *); 512extern int qla82xx_pinit_from_rom(scsi_qla_host_t *);
513extern void qla82xx_watchdog(scsi_qla_host_t *); 513extern void qla82xx_watchdog(scsi_qla_host_t *);
514extern int qla82xx_start_firmware(scsi_qla_host_t *);
514 515
515/* Firmware and flash related functions */ 516/* Firmware and flash related functions */
516extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *); 517extern int qla82xx_load_risc(scsi_qla_host_t *, uint32_t *);
@@ -538,6 +539,7 @@ extern void qla82xx_poll(int, void *);
538extern void qla82xx_init_flags(struct qla_hw_data *); 539extern void qla82xx_init_flags(struct qla_hw_data *);
539 540
540/* ISP 8021 hardware related */ 541/* ISP 8021 hardware related */
542extern void qla82xx_set_drv_active(scsi_qla_host_t *);
541extern int qla82xx_crb_win_lock(struct qla_hw_data *); 543extern int qla82xx_crb_win_lock(struct qla_hw_data *);
542extern void qla82xx_crb_win_unlock(struct qla_hw_data *); 544extern void qla82xx_crb_win_unlock(struct qla_hw_data *);
543extern int qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *, ulong *); 545extern int qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *, ulong *);
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 915b77a6e193..2ad91100a7e4 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -2257,7 +2257,7 @@ void qla82xx_init_flags(struct qla_hw_data *ha)
2257 ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg; 2257 ha->nx_legacy_intr.pci_int_reg = nx_legacy_intr->pci_int_reg;
2258} 2258}
2259 2259
2260static inline void 2260inline void
2261qla82xx_set_drv_active(scsi_qla_host_t *vha) 2261qla82xx_set_drv_active(scsi_qla_host_t *vha)
2262{ 2262{
2263 uint32_t drv_active; 2263 uint32_t drv_active;
@@ -2411,7 +2411,7 @@ fw_load_failed:
2411 return QLA_FUNCTION_FAILED; 2411 return QLA_FUNCTION_FAILED;
2412} 2412}
2413 2413
2414static int 2414int
2415qla82xx_start_firmware(scsi_qla_host_t *vha) 2415qla82xx_start_firmware(scsi_qla_host_t *vha)
2416{ 2416{
2417 int pcie_cap; 2417 int pcie_cap;
@@ -3291,6 +3291,9 @@ qla82xx_check_fw_alive(scsi_qla_host_t *vha)
3291 struct qla_hw_data *ha = vha->hw; 3291 struct qla_hw_data *ha = vha->hw;
3292 3292
3293 fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); 3293 fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
3294 /* all 0xff, assume AER/EEH in progress, ignore */
3295 if (fw_heartbeat_counter == 0xffffffff)
3296 return;
3294 if (vha->fw_heartbeat_counter == fw_heartbeat_counter) { 3297 if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
3295 vha->seconds_since_last_heartbeat++; 3298 vha->seconds_since_last_heartbeat++;
3296 /* FW not alive after 2 seconds */ 3299 /* FW not alive after 2 seconds */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 30b05229af26..cfa55827a101 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3526,6 +3526,11 @@ qla2x00_timer(scsi_qla_host_t *vha)
3526 struct qla_hw_data *ha = vha->hw; 3526 struct qla_hw_data *ha = vha->hw;
3527 struct req_que *req; 3527 struct req_que *req;
3528 3528
3529 if (ha->flags.eeh_busy) {
3530 qla2x00_restart_timer(vha, WATCH_INTERVAL);
3531 return;
3532 }
3533
3529 if (IS_QLA82XX(ha)) 3534 if (IS_QLA82XX(ha))
3530 qla82xx_watchdog(vha); 3535 qla82xx_watchdog(vha);
3531 3536
@@ -3755,6 +3760,17 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
3755 return PCI_ERS_RESULT_CAN_RECOVER; 3760 return PCI_ERS_RESULT_CAN_RECOVER;
3756 case pci_channel_io_frozen: 3761 case pci_channel_io_frozen:
3757 ha->flags.eeh_busy = 1; 3762 ha->flags.eeh_busy = 1;
3763 /* For ISP82XX complete any pending mailbox cmd */
3764 if (IS_QLA82XX(ha)) {
3765 ha->flags.fw_hung = 1;
3766 if (ha->flags.mbox_busy) {
3767 ha->flags.mbox_int = 1;
3768 DEBUG2(qla_printk(KERN_ERR, ha,
3769 "Due to pci channel io frozen, doing premature "
3770 "completion of mbx command\n"));
3771 complete(&ha->mbx_intr_comp);
3772 }
3773 }
3758 qla2x00_free_irqs(vha); 3774 qla2x00_free_irqs(vha);
3759 pci_disable_device(pdev); 3775 pci_disable_device(pdev);
3760 return PCI_ERS_RESULT_NEED_RESET; 3776 return PCI_ERS_RESULT_NEED_RESET;
@@ -3803,6 +3819,109 @@ qla2xxx_pci_mmio_enabled(struct pci_dev *pdev)
3803 return PCI_ERS_RESULT_RECOVERED; 3819 return PCI_ERS_RESULT_RECOVERED;
3804} 3820}
3805 3821
3822uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
3823{
3824 uint32_t rval = QLA_FUNCTION_FAILED;
3825 uint32_t drv_active = 0;
3826 struct qla_hw_data *ha = base_vha->hw;
3827 int fn;
3828 struct pci_dev *other_pdev = NULL;
3829
3830 DEBUG17(qla_printk(KERN_INFO, ha,
3831 "scsi(%ld): In qla82xx_error_recovery\n", base_vha->host_no));
3832
3833 set_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3834
3835 if (base_vha->flags.online) {
3836 /* Abort all outstanding commands,
3837 * so as to be requeued later */
3838 qla2x00_abort_isp_cleanup(base_vha);
3839 }
3840
3841
3842 fn = PCI_FUNC(ha->pdev->devfn);
3843 while (fn > 0) {
3844 fn--;
3845 DEBUG17(qla_printk(KERN_INFO, ha,
3846 "Finding pci device at function = 0x%x\n", fn));
3847 other_pdev =
3848 pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
3849 ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
3850 fn));
3851
3852 if (!other_pdev)
3853 continue;
3854 if (atomic_read(&other_pdev->enable_cnt)) {
3855 DEBUG17(qla_printk(KERN_INFO, ha,
3856 "Found PCI func availabe and enabled at 0x%x\n",
3857 fn));
3858 pci_dev_put(other_pdev);
3859 break;
3860 }
3861 pci_dev_put(other_pdev);
3862 }
3863
3864 if (!fn) {
3865 /* Reset owner */
3866 DEBUG17(qla_printk(KERN_INFO, ha,
3867 "This devfn is reset owner = 0x%x\n", ha->pdev->devfn));
3868 qla82xx_idc_lock(ha);
3869
3870 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3871 QLA82XX_DEV_INITIALIZING);
3872
3873 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
3874 QLA82XX_IDC_VERSION);
3875
3876 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
3877 DEBUG17(qla_printk(KERN_INFO, ha,
3878 "drv_active = 0x%x\n", drv_active));
3879
3880 qla82xx_idc_unlock(ha);
3881 /* Reset if device is not already reset
3882 * drv_active would be 0 if a reset has already been done
3883 */
3884 if (drv_active)
3885 rval = qla82xx_start_firmware(base_vha);
3886 else
3887 rval = QLA_SUCCESS;
3888 qla82xx_idc_lock(ha);
3889
3890 if (rval != QLA_SUCCESS) {
3891 qla_printk(KERN_INFO, ha, "HW State: FAILED\n");
3892 qla82xx_clear_drv_active(ha);
3893 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3894 QLA82XX_DEV_FAILED);
3895 } else {
3896 qla_printk(KERN_INFO, ha, "HW State: READY\n");
3897 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3898 QLA82XX_DEV_READY);
3899 qla82xx_idc_unlock(ha);
3900 ha->flags.fw_hung = 0;
3901 rval = qla82xx_restart_isp(base_vha);
3902 qla82xx_idc_lock(ha);
3903 /* Clear driver state register */
3904 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0);
3905 qla82xx_set_drv_active(base_vha);
3906 }
3907 qla82xx_idc_unlock(ha);
3908 } else {
3909 DEBUG17(qla_printk(KERN_INFO, ha,
3910 "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
3911 if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
3912 QLA82XX_DEV_READY)) {
3913 ha->flags.fw_hung = 0;
3914 rval = qla82xx_restart_isp(base_vha);
3915 qla82xx_idc_lock(ha);
3916 qla82xx_set_drv_active(base_vha);
3917 qla82xx_idc_unlock(ha);
3918 }
3919 }
3920 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3921
3922 return rval;
3923}
3924
3806static pci_ers_result_t 3925static pci_ers_result_t
3807qla2xxx_pci_slot_reset(struct pci_dev *pdev) 3926qla2xxx_pci_slot_reset(struct pci_dev *pdev)
3808{ 3927{
@@ -3835,15 +3954,23 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
3835 if (rc) { 3954 if (rc) {
3836 qla_printk(KERN_WARNING, ha, 3955 qla_printk(KERN_WARNING, ha,
3837 "Can't re-enable PCI device after reset.\n"); 3956 "Can't re-enable PCI device after reset.\n");
3838 return ret; 3957 goto exit_slot_reset;
3839 } 3958 }
3840 3959
3841 rsp = ha->rsp_q_map[0]; 3960 rsp = ha->rsp_q_map[0];
3842 if (qla2x00_request_irqs(ha, rsp)) 3961 if (qla2x00_request_irqs(ha, rsp))
3843 return ret; 3962 goto exit_slot_reset;
3844 3963
3845 if (ha->isp_ops->pci_config(base_vha)) 3964 if (ha->isp_ops->pci_config(base_vha))
3846 return ret; 3965 goto exit_slot_reset;
3966
3967 if (IS_QLA82XX(ha)) {
3968 if (qla82xx_error_recovery(base_vha) == QLA_SUCCESS) {
3969 ret = PCI_ERS_RESULT_RECOVERED;
3970 goto exit_slot_reset;
3971 } else
3972 goto exit_slot_reset;
3973 }
3847 3974
3848 while (ha->flags.mbox_busy && retries--) 3975 while (ha->flags.mbox_busy && retries--)
3849 msleep(1000); 3976 msleep(1000);
@@ -3854,6 +3981,7 @@ qla2xxx_pci_slot_reset(struct pci_dev *pdev)
3854 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags); 3981 clear_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags);
3855 3982
3856 3983
3984exit_slot_reset:
3857 DEBUG17(qla_printk(KERN_WARNING, ha, 3985 DEBUG17(qla_printk(KERN_WARNING, ha,
3858 "slot_reset-return:ret=%x\n", ret)); 3986 "slot_reset-return:ret=%x\n", ret));
3859 3987