aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorSantosh Vernekar <santosh.vernekar@qlogic.com>2012-08-22 14:21:03 -0400
committerJames Bottomley <JBottomley@Parallels.com>2012-09-24 04:10:47 -0400
commit7d613ac6acec8c29e7aa3f80e28e8e982977a151 (patch)
treeeec782c42537c4658850ffb8982973f122e388a2 /drivers/scsi/qla2xxx/qla_os.c
parent40129a4c6edc1753b9a537877b6a2eac9fc6c659 (diff)
[SCSI] qla2xxx: IDC implementation for ISP83xx.
Signed-off-by: Santosh Vernekar <santosh.vernekar@qlogic.com> Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c684
1 files changed, 676 insertions, 8 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3e775650c20c..c705a51ee333 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2149,7 +2149,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2149 scsi_qla_host_t *base_vha = NULL; 2149 scsi_qla_host_t *base_vha = NULL;
2150 struct qla_hw_data *ha; 2150 struct qla_hw_data *ha;
2151 char pci_info[30]; 2151 char pci_info[30];
2152 char fw_str[30]; 2152 char fw_str[30], wq_name[30];
2153 struct scsi_host_template *sht; 2153 struct scsi_host_template *sht;
2154 int bars, mem_only = 0; 2154 int bars, mem_only = 0;
2155 uint16_t req_length = 0, rsp_length = 0; 2155 uint16_t req_length = 0, rsp_length = 0;
@@ -2319,6 +2319,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2319 ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF; 2319 ha->nvram_conf_off = FARX_ACCESS_NVRAM_CONF;
2320 ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA; 2320 ha->nvram_data_off = FARX_ACCESS_NVRAM_DATA;
2321 } else if (IS_QLA83XX(ha)) { 2321 } else if (IS_QLA83XX(ha)) {
2322 ha->portnum = PCI_FUNC(ha->pdev->devfn);
2322 ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400; 2323 ha->max_fibre_devices = MAX_FIBRE_DEVICES_2400;
2323 ha->mbx_count = MAILBOX_REGISTER_COUNT; 2324 ha->mbx_count = MAILBOX_REGISTER_COUNT;
2324 req_length = REQUEST_ENTRY_CNT_24XX; 2325 req_length = REQUEST_ENTRY_CNT_24XX;
@@ -2403,6 +2404,20 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
2403 base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER + 2404 base_vha->mgmt_svr_loop_id = MANAGEMENT_SERVER +
2404 base_vha->vp_idx; 2405 base_vha->vp_idx;
2405 2406
2407 if (IS_QLA8031(ha)) {
2408 sprintf(wq_name, "qla2xxx_%lu_dpc_lp_wq", base_vha->host_no);
2409 ha->dpc_lp_wq = create_singlethread_workqueue(wq_name);
2410 INIT_WORK(&ha->idc_aen, qla83xx_service_idc_aen);
2411
2412 sprintf(wq_name, "qla2xxx_%lu_dpc_hp_wq", base_vha->host_no);
2413 ha->dpc_hp_wq = create_singlethread_workqueue(wq_name);
2414 INIT_WORK(&ha->nic_core_reset, qla83xx_nic_core_reset_work);
2415 INIT_WORK(&ha->idc_state_handler,
2416 qla83xx_idc_state_handler_work);
2417 INIT_WORK(&ha->nic_core_unrecoverable,
2418 qla83xx_nic_core_unrecoverable_work);
2419 }
2420
2406 /* Set the SG table size based on ISP type */ 2421 /* Set the SG table size based on ISP type */
2407 if (!IS_FWI2_CAPABLE(ha)) { 2422 if (!IS_FWI2_CAPABLE(ha)) {
2408 if (IS_QLA2100(ha)) 2423 if (IS_QLA2100(ha))
@@ -2500,7 +2515,7 @@ que_init:
2500 if (IS_QLA82XX(ha)) { 2515 if (IS_QLA82XX(ha)) {
2501 qla82xx_idc_lock(ha); 2516 qla82xx_idc_lock(ha);
2502 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 2517 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
2503 QLA82XX_DEV_FAILED); 2518 QLA8XXX_DEV_FAILED);
2504 qla82xx_idc_unlock(ha); 2519 qla82xx_idc_unlock(ha);
2505 ql_log(ql_log_fatal, base_vha, 0x00d7, 2520 ql_log(ql_log_fatal, base_vha, 0x00d7,
2506 "HW State: FAILED.\n"); 2521 "HW State: FAILED.\n");
@@ -2751,6 +2766,14 @@ qla2x00_remove_one(struct pci_dev *pdev)
2751 } 2766 }
2752 mutex_unlock(&ha->vport_lock); 2767 mutex_unlock(&ha->vport_lock);
2753 2768
2769 if (IS_QLA8031(ha)) {
2770 ql_dbg(ql_dbg_p3p, base_vha, 0xb07e,
2771 "Clearing fcoe driver presence.\n");
2772 if (qla83xx_clear_drv_presence(base_vha) != QLA_SUCCESS)
2773 ql_dbg(ql_dbg_p3p, base_vha, 0xb079,
2774 "Error while clearing DRV-Presence.\n");
2775 }
2776
2754 set_bit(UNLOADING, &base_vha->dpc_flags); 2777 set_bit(UNLOADING, &base_vha->dpc_flags);
2755 2778
2756 qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16); 2779 qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
@@ -2772,6 +2795,21 @@ qla2x00_remove_one(struct pci_dev *pdev)
2772 ha->wq = NULL; 2795 ha->wq = NULL;
2773 } 2796 }
2774 2797
2798 /* Cancel all work and destroy DPC workqueues */
2799 if (ha->dpc_lp_wq) {
2800 cancel_work_sync(&ha->idc_aen);
2801 destroy_workqueue(ha->dpc_lp_wq);
2802 ha->dpc_lp_wq = NULL;
2803 }
2804
2805 if (ha->dpc_hp_wq) {
2806 cancel_work_sync(&ha->nic_core_reset);
2807 cancel_work_sync(&ha->idc_state_handler);
2808 cancel_work_sync(&ha->nic_core_unrecoverable);
2809 destroy_workqueue(ha->dpc_hp_wq);
2810 ha->dpc_hp_wq = NULL;
2811 }
2812
2775 /* Kill the kernel thread for this host */ 2813 /* Kill the kernel thread for this host */
2776 if (ha->dpc_thread) { 2814 if (ha->dpc_thread) {
2777 struct task_struct *t = ha->dpc_thread; 2815 struct task_struct *t = ha->dpc_thread;
@@ -2838,7 +2876,6 @@ qla2x00_free_device(scsi_qla_host_t *vha)
2838 qla2x00_stop_dpc_thread(vha); 2876 qla2x00_stop_dpc_thread(vha);
2839 2877
2840 qla25xx_delete_queues(vha); 2878 qla25xx_delete_queues(vha);
2841
2842 if (ha->flags.fce_enabled) 2879 if (ha->flags.fce_enabled)
2843 qla2x00_disable_fce_trace(vha, NULL, NULL); 2880 qla2x00_disable_fce_trace(vha, NULL, NULL);
2844 2881
@@ -3709,6 +3746,637 @@ void qla2x00_relogin(struct scsi_qla_host *vha)
3709 } 3746 }
3710} 3747}
3711 3748
3749/* Schedule work on any of the dpc-workqueues */
3750void
3751qla83xx_schedule_work(scsi_qla_host_t *base_vha, int work_code)
3752{
3753 struct qla_hw_data *ha = base_vha->hw;
3754
3755 switch (work_code) {
3756 case MBA_IDC_AEN: /* 0x8200 */
3757 if (ha->dpc_lp_wq)
3758 queue_work(ha->dpc_lp_wq, &ha->idc_aen);
3759 break;
3760
3761 case QLA83XX_NIC_CORE_RESET: /* 0x1 */
3762 if (!ha->flags.nic_core_reset_hdlr_active) {
3763 if (ha->dpc_hp_wq)
3764 queue_work(ha->dpc_hp_wq, &ha->nic_core_reset);
3765 } else
3766 ql_dbg(ql_dbg_p3p, base_vha, 0xb05e,
3767 "NIC Core reset is already active. Skip "
3768 "scheduling it again.\n");
3769 break;
3770 case QLA83XX_IDC_STATE_HANDLER: /* 0x2 */
3771 if (ha->dpc_hp_wq)
3772 queue_work(ha->dpc_hp_wq, &ha->idc_state_handler);
3773 break;
3774 case QLA83XX_NIC_CORE_UNRECOVERABLE: /* 0x3 */
3775 if (ha->dpc_hp_wq)
3776 queue_work(ha->dpc_hp_wq, &ha->nic_core_unrecoverable);
3777 break;
3778 default:
3779 ql_log(ql_log_warn, base_vha, 0xb05f,
3780 "Unknow work-code=0x%x.\n", work_code);
3781 }
3782
3783 return;
3784}
3785
3786/* Work: Perform NIC Core Unrecoverable state handling */
3787void
3788qla83xx_nic_core_unrecoverable_work(struct work_struct *work)
3789{
3790 struct qla_hw_data *ha =
3791 container_of(work, struct qla_hw_data, nic_core_reset);
3792 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
3793 uint32_t dev_state = 0;
3794
3795 qla83xx_idc_lock(base_vha, 0);
3796 qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state);
3797 qla83xx_reset_ownership(base_vha);
3798 if (ha->flags.nic_core_reset_owner) {
3799 ha->flags.nic_core_reset_owner = 0;
3800 qla83xx_wr_reg(base_vha, QLA83XX_IDC_DEV_STATE,
3801 QLA8XXX_DEV_FAILED);
3802 ql_log(ql_log_info, base_vha, 0xb060, "HW State: FAILED.\n");
3803 qla83xx_schedule_work(base_vha, QLA83XX_IDC_STATE_HANDLER);
3804 }
3805 qla83xx_idc_unlock(base_vha, 0);
3806}
3807
3808/* Work: Execute IDC state handler */
3809void
3810qla83xx_idc_state_handler_work(struct work_struct *work)
3811{
3812 struct qla_hw_data *ha =
3813 container_of(work, struct qla_hw_data, nic_core_reset);
3814 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
3815 uint32_t dev_state = 0;
3816
3817 qla83xx_idc_lock(base_vha, 0);
3818 qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state);
3819 if (dev_state == QLA8XXX_DEV_FAILED ||
3820 dev_state == QLA8XXX_DEV_NEED_QUIESCENT)
3821 qla83xx_idc_state_handler(base_vha);
3822 qla83xx_idc_unlock(base_vha, 0);
3823}
3824
3825int
3826qla83xx_check_nic_core_fw_alive(scsi_qla_host_t *base_vha)
3827{
3828 int rval = QLA_SUCCESS;
3829 unsigned long heart_beat_wait = jiffies + (1 * HZ);
3830 uint32_t heart_beat_counter1, heart_beat_counter2;
3831
3832 do {
3833 if (time_after(jiffies, heart_beat_wait)) {
3834 ql_dbg(ql_dbg_p3p, base_vha, 0xb07c,
3835 "Nic Core f/w is not alive.\n");
3836 rval = QLA_FUNCTION_FAILED;
3837 break;
3838 }
3839
3840 qla83xx_idc_lock(base_vha, 0);
3841 qla83xx_rd_reg(base_vha, QLA83XX_FW_HEARTBEAT,
3842 &heart_beat_counter1);
3843 qla83xx_idc_unlock(base_vha, 0);
3844 msleep(100);
3845 qla83xx_idc_lock(base_vha, 0);
3846 qla83xx_rd_reg(base_vha, QLA83XX_FW_HEARTBEAT,
3847 &heart_beat_counter2);
3848 qla83xx_idc_unlock(base_vha, 0);
3849 } while (heart_beat_counter1 == heart_beat_counter2);
3850
3851 return rval;
3852}
3853
3854/* Work: Perform NIC Core Reset handling */
3855void
3856qla83xx_nic_core_reset_work(struct work_struct *work)
3857{
3858 struct qla_hw_data *ha =
3859 container_of(work, struct qla_hw_data, nic_core_reset);
3860 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
3861 uint32_t dev_state = 0;
3862
3863 if (!ha->flags.nic_core_reset_hdlr_active) {
3864 if (qla83xx_check_nic_core_fw_alive(base_vha) == QLA_SUCCESS) {
3865 qla83xx_idc_lock(base_vha, 0);
3866 qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE,
3867 &dev_state);
3868 qla83xx_idc_unlock(base_vha, 0);
3869 if (dev_state != QLA8XXX_DEV_NEED_RESET) {
3870 ql_dbg(ql_dbg_p3p, base_vha, 0xb07a,
3871 "Nic Core f/w is alive.\n");
3872 return;
3873 }
3874 }
3875
3876 ha->flags.nic_core_reset_hdlr_active = 1;
3877 if (qla83xx_nic_core_reset(base_vha)) {
3878 /* NIC Core reset failed. */
3879 ql_dbg(ql_dbg_p3p, base_vha, 0xb061,
3880 "NIC Core reset failed.\n");
3881 }
3882 ha->flags.nic_core_reset_hdlr_active = 0;
3883 }
3884}
3885
3886/* Work: Handle 8200 IDC aens */
3887void
3888qla83xx_service_idc_aen(struct work_struct *work)
3889{
3890 struct qla_hw_data *ha =
3891 container_of(work, struct qla_hw_data, idc_aen);
3892 scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
3893 uint32_t dev_state, idc_control;
3894
3895 qla83xx_idc_lock(base_vha, 0);
3896 qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state);
3897 qla83xx_rd_reg(base_vha, QLA83XX_IDC_CONTROL, &idc_control);
3898 qla83xx_idc_unlock(base_vha, 0);
3899 if (dev_state == QLA8XXX_DEV_NEED_RESET) {
3900 if (idc_control & QLA83XX_IDC_GRACEFUL_RESET) {
3901 ql_dbg(ql_dbg_p3p, base_vha, 0xb062,
3902 "Application requested NIC Core Reset.\n");
3903 qla83xx_schedule_work(base_vha, QLA83XX_NIC_CORE_RESET);
3904 } else if (qla83xx_check_nic_core_fw_alive(base_vha) ==
3905 QLA_SUCCESS) {
3906 ql_dbg(ql_dbg_p3p, base_vha, 0xb07b,
3907 "Other protocol driver requested NIC Core Reset.\n");
3908 qla83xx_schedule_work(base_vha, QLA83XX_NIC_CORE_RESET);
3909 }
3910 } else if (dev_state == QLA8XXX_DEV_FAILED ||
3911 dev_state == QLA8XXX_DEV_NEED_QUIESCENT) {
3912 qla83xx_schedule_work(base_vha, QLA83XX_IDC_STATE_HANDLER);
3913 }
3914}
3915
3916static void
3917qla83xx_wait_logic(void)
3918{
3919 int i;
3920
3921 /* Yield CPU */
3922 if (!in_interrupt()) {
3923 /*
3924 * Wait about 200ms before retrying again.
3925 * This controls the number of retries for single
3926 * lock operation.
3927 */
3928 msleep(100);
3929 schedule();
3930 } else {
3931 for (i = 0; i < 20; i++)
3932 cpu_relax(); /* This a nop instr on i386 */
3933 }
3934}
3935
3936int
3937qla83xx_force_lock_recovery(scsi_qla_host_t *base_vha)
3938{
3939 int rval;
3940 uint32_t data;
3941 uint32_t idc_lck_rcvry_stage_mask = 0x3;
3942 uint32_t idc_lck_rcvry_owner_mask = 0x3c;
3943 struct qla_hw_data *ha = base_vha->hw;
3944
3945 rval = qla83xx_rd_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY, &data);
3946 if (rval)
3947 return rval;
3948
3949 if ((data & idc_lck_rcvry_stage_mask) > 0) {
3950 return QLA_SUCCESS;
3951 } else {
3952 data = (IDC_LOCK_RECOVERY_STAGE1) | (ha->portnum << 2);
3953 rval = qla83xx_wr_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY,
3954 data);
3955 if (rval)
3956 return rval;
3957
3958 msleep(200);
3959
3960 rval = qla83xx_rd_reg(base_vha, QLA83XX_IDC_LOCK_RECOVERY,
3961 &data);
3962 if (rval)
3963 return rval;
3964
3965 if (((data & idc_lck_rcvry_owner_mask) >> 2) == ha->portnum) {
3966 data &= (IDC_LOCK_RECOVERY_STAGE2 |
3967 ~(idc_lck_rcvry_stage_mask));
3968 rval = qla83xx_wr_reg(base_vha,
3969 QLA83XX_IDC_LOCK_RECOVERY, data);
3970 if (rval)
3971 return rval;
3972
3973 /* Forcefully perform IDC UnLock */
3974 rval = qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_UNLOCK,
3975 &data);
3976 if (rval)
3977 return rval;
3978 /* Clear lock-id by setting 0xff */
3979 rval = qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID,
3980 0xff);
3981 if (rval)
3982 return rval;
3983 /* Clear lock-recovery by setting 0x0 */
3984 rval = qla83xx_wr_reg(base_vha,
3985 QLA83XX_IDC_LOCK_RECOVERY, 0x0);
3986 if (rval)
3987 return rval;
3988 } else
3989 return QLA_SUCCESS;
3990 }
3991
3992 return rval;
3993}
3994
3995int
3996qla83xx_idc_lock_recovery(scsi_qla_host_t *base_vha)
3997{
3998 int rval = QLA_SUCCESS;
3999 uint32_t o_drv_lockid, n_drv_lockid;
4000 unsigned long lock_recovery_timeout;
4001
4002 lock_recovery_timeout = jiffies + QLA83XX_MAX_LOCK_RECOVERY_WAIT;
4003retry_lockid:
4004 rval = qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, &o_drv_lockid);
4005 if (rval)
4006 goto exit;
4007
4008 /* MAX wait time before forcing IDC Lock recovery = 2 secs */
4009 if (time_after_eq(jiffies, lock_recovery_timeout)) {
4010 if (qla83xx_force_lock_recovery(base_vha) == QLA_SUCCESS)
4011 return QLA_SUCCESS;
4012 else
4013 return QLA_FUNCTION_FAILED;
4014 }
4015
4016 rval = qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, &n_drv_lockid);
4017 if (rval)
4018 goto exit;
4019
4020 if (o_drv_lockid == n_drv_lockid) {
4021 qla83xx_wait_logic();
4022 goto retry_lockid;
4023 } else
4024 return QLA_SUCCESS;
4025
4026exit:
4027 return rval;
4028}
4029
4030void
4031qla83xx_idc_lock(scsi_qla_host_t *base_vha, uint16_t requester_id)
4032{
4033 uint16_t options = (requester_id << 15) | BIT_6;
4034 uint32_t data;
4035 struct qla_hw_data *ha = base_vha->hw;
4036
4037 /* IDC-lock implementation using driver-lock/lock-id remote registers */
4038retry_lock:
4039 if (qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCK, &data)
4040 == QLA_SUCCESS) {
4041 if (data) {
4042 /* Setting lock-id to our function-number */
4043 qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID,
4044 ha->portnum);
4045 } else {
4046 ql_dbg(ql_dbg_p3p, base_vha, 0xb063,
4047 "Failed to acquire IDC lock. retrying...\n");
4048
4049 /* Retry/Perform IDC-Lock recovery */
4050 if (qla83xx_idc_lock_recovery(base_vha)
4051 == QLA_SUCCESS) {
4052 qla83xx_wait_logic();
4053 goto retry_lock;
4054 } else
4055 ql_log(ql_log_warn, base_vha, 0xb075,
4056 "IDC Lock recovery FAILED.\n");
4057 }
4058
4059 }
4060
4061 return;
4062
4063 /* XXX: IDC-lock implementation using access-control mbx */
4064retry_lock2:
4065 if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) {
4066 ql_dbg(ql_dbg_p3p, base_vha, 0xb072,
4067 "Failed to acquire IDC lock. retrying...\n");
4068 /* Retry/Perform IDC-Lock recovery */
4069 if (qla83xx_idc_lock_recovery(base_vha) == QLA_SUCCESS) {
4070 qla83xx_wait_logic();
4071 goto retry_lock2;
4072 } else
4073 ql_log(ql_log_warn, base_vha, 0xb076,
4074 "IDC Lock recovery FAILED.\n");
4075 }
4076
4077 return;
4078}
4079
4080void
4081qla83xx_idc_unlock(scsi_qla_host_t *base_vha, uint16_t requester_id)
4082{
4083 uint16_t options = (requester_id << 15) | BIT_7, retry;
4084 uint32_t data;
4085 struct qla_hw_data *ha = base_vha->hw;
4086
4087 /* IDC-unlock implementation using driver-unlock/lock-id
4088 * remote registers
4089 */
4090 retry = 0;
4091retry_unlock:
4092 if (qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_LOCKID, &data)
4093 == QLA_SUCCESS) {
4094 if (data == ha->portnum) {
4095 qla83xx_rd_reg(base_vha, QLA83XX_DRIVER_UNLOCK, &data);
4096 /* Clearing lock-id by setting 0xff */
4097 qla83xx_wr_reg(base_vha, QLA83XX_DRIVER_LOCKID, 0xff);
4098 } else if (retry < 10) {
4099 /* SV: XXX: IDC unlock retrying needed here? */
4100
4101 /* Retry for IDC-unlock */
4102 qla83xx_wait_logic();
4103 retry++;
4104 ql_dbg(ql_dbg_p3p, base_vha, 0xb064,
4105 "Failed to release IDC lock, retyring=%d\n", retry);
4106 goto retry_unlock;
4107 }
4108 } else if (retry < 10) {
4109 /* Retry for IDC-unlock */
4110 qla83xx_wait_logic();
4111 retry++;
4112 ql_dbg(ql_dbg_p3p, base_vha, 0xb065,
4113 "Failed to read drv-lockid, retyring=%d\n", retry);
4114 goto retry_unlock;
4115 }
4116
4117 return;
4118
4119 /* XXX: IDC-unlock implementation using access-control mbx */
4120 retry = 0;
4121retry_unlock2:
4122 if (qla83xx_access_control(base_vha, options, 0, 0, NULL)) {
4123 if (retry < 10) {
4124 /* Retry for IDC-unlock */
4125 qla83xx_wait_logic();
4126 retry++;
4127 ql_dbg(ql_dbg_p3p, base_vha, 0xb066,
4128 "Failed to release IDC lock, retyring=%d\n", retry);
4129 goto retry_unlock2;
4130 }
4131 }
4132
4133 return;
4134}
4135
4136int
4137__qla83xx_set_drv_presence(scsi_qla_host_t *vha)
4138{
4139 int rval = QLA_SUCCESS;
4140 struct qla_hw_data *ha = vha->hw;
4141 uint32_t drv_presence;
4142
4143 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
4144 if (rval == QLA_SUCCESS) {
4145 drv_presence |= (1 << ha->portnum);
4146 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRV_PRESENCE,
4147 drv_presence);
4148 }
4149
4150 return rval;
4151}
4152
4153int
4154qla83xx_set_drv_presence(scsi_qla_host_t *vha)
4155{
4156 int rval = QLA_SUCCESS;
4157
4158 qla83xx_idc_lock(vha, 0);
4159 rval = __qla83xx_set_drv_presence(vha);
4160 qla83xx_idc_unlock(vha, 0);
4161
4162 return rval;
4163}
4164
4165int
4166__qla83xx_clear_drv_presence(scsi_qla_host_t *vha)
4167{
4168 int rval = QLA_SUCCESS;
4169 struct qla_hw_data *ha = vha->hw;
4170 uint32_t drv_presence;
4171
4172 rval = qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
4173 if (rval == QLA_SUCCESS) {
4174 drv_presence &= ~(1 << ha->portnum);
4175 rval = qla83xx_wr_reg(vha, QLA83XX_IDC_DRV_PRESENCE,
4176 drv_presence);
4177 }
4178
4179 return rval;
4180}
4181
4182int
4183qla83xx_clear_drv_presence(scsi_qla_host_t *vha)
4184{
4185 int rval = QLA_SUCCESS;
4186
4187 qla83xx_idc_lock(vha, 0);
4188 rval = __qla83xx_clear_drv_presence(vha);
4189 qla83xx_idc_unlock(vha, 0);
4190
4191 return rval;
4192}
4193
4194void
4195qla83xx_need_reset_handler(scsi_qla_host_t *vha)
4196{
4197 struct qla_hw_data *ha = vha->hw;
4198 uint32_t drv_ack, drv_presence;
4199 unsigned long ack_timeout;
4200
4201 /* Wait for IDC ACK from all functions (DRV-ACK == DRV-PRESENCE) */
4202 ack_timeout = jiffies + (ha->fcoe_reset_timeout * HZ);
4203 while (1) {
4204 qla83xx_rd_reg(vha, QLA83XX_IDC_DRIVER_ACK, &drv_ack);
4205 qla83xx_rd_reg(vha, QLA83XX_IDC_DRV_PRESENCE, &drv_presence);
4206 if (drv_ack == drv_presence)
4207 break;
4208
4209 if (time_after_eq(jiffies, ack_timeout)) {
4210 ql_log(ql_log_warn, vha, 0xb067,
4211 "RESET ACK TIMEOUT! drv_presence=0x%x "
4212 "drv_ack=0x%x\n", drv_presence, drv_ack);
4213 /*
4214 * The function(s) which did not ack in time are forced
4215 * to withdraw any further participation in the IDC
4216 * reset.
4217 */
4218 if (drv_ack != drv_presence)
4219 qla83xx_wr_reg(vha, QLA83XX_IDC_DRV_PRESENCE,
4220 drv_ack);
4221 break;
4222 }
4223
4224 qla83xx_idc_unlock(vha, 0);
4225 msleep(1000);
4226 qla83xx_idc_lock(vha, 0);
4227 }
4228
4229 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_COLD);
4230 ql_log(ql_log_info, vha, 0xb068, "HW State: COLD/RE-INIT.\n");
4231}
4232
4233int
4234qla83xx_device_bootstrap(scsi_qla_host_t *vha)
4235{
4236 int rval = QLA_SUCCESS;
4237 uint32_t idc_control;
4238
4239 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_INITIALIZING);
4240 ql_log(ql_log_info, vha, 0xb069, "HW State: INITIALIZING.\n");
4241
4242 /* Clearing IDC-Control Graceful-Reset Bit before resetting f/w */
4243 __qla83xx_get_idc_control(vha, &idc_control);
4244 idc_control &= ~QLA83XX_IDC_GRACEFUL_RESET;
4245 __qla83xx_set_idc_control(vha, 0);
4246
4247 qla83xx_idc_unlock(vha, 0);
4248 rval = qla83xx_restart_nic_firmware(vha);
4249 qla83xx_idc_lock(vha, 0);
4250
4251 if (rval != QLA_SUCCESS) {
4252 ql_log(ql_log_fatal, vha, 0xb06a,
4253 "Failed to restart NIC f/w.\n");
4254 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_FAILED);
4255 ql_log(ql_log_info, vha, 0xb06b, "HW State: FAILED.\n");
4256 } else {
4257 ql_dbg(ql_dbg_p3p, vha, 0xb06c,
4258 "Success in restarting nic f/w.\n");
4259 qla83xx_wr_reg(vha, QLA83XX_IDC_DEV_STATE, QLA8XXX_DEV_READY);
4260 ql_log(ql_log_info, vha, 0xb06d, "HW State: READY.\n");
4261 }
4262
4263 return rval;
4264}
4265
4266/* Assumes idc_lock always held on entry */
4267int
4268qla83xx_idc_state_handler(scsi_qla_host_t *base_vha)
4269{
4270 struct qla_hw_data *ha = base_vha->hw;
4271 int rval = QLA_SUCCESS;
4272 unsigned long dev_init_timeout;
4273 uint32_t dev_state;
4274
4275 /* Wait for MAX-INIT-TIMEOUT for the device to go ready */
4276 dev_init_timeout = jiffies + (ha->fcoe_dev_init_timeout * HZ);
4277
4278 while (1) {
4279
4280 if (time_after_eq(jiffies, dev_init_timeout)) {
4281 ql_log(ql_log_warn, base_vha, 0xb06e,
4282 "Initialization TIMEOUT!\n");
4283 /* Init timeout. Disable further NIC Core
4284 * communication.
4285 */
4286 qla83xx_wr_reg(base_vha, QLA83XX_IDC_DEV_STATE,
4287 QLA8XXX_DEV_FAILED);
4288 ql_log(ql_log_info, base_vha, 0xb06f,
4289 "HW State: FAILED.\n");
4290 }
4291
4292 qla83xx_rd_reg(base_vha, QLA83XX_IDC_DEV_STATE, &dev_state);
4293 switch (dev_state) {
4294 case QLA8XXX_DEV_READY:
4295 if (ha->flags.nic_core_reset_owner)
4296 qla83xx_idc_audit(base_vha,
4297 IDC_AUDIT_COMPLETION);
4298 ha->flags.nic_core_reset_owner = 0;
4299 ql_dbg(ql_dbg_p3p, base_vha, 0xb070,
4300 "Reset_owner reset by 0x%x.\n",
4301 ha->portnum);
4302 goto exit;
4303 case QLA8XXX_DEV_COLD:
4304 if (ha->flags.nic_core_reset_owner)
4305 rval = qla83xx_device_bootstrap(base_vha);
4306 else {
4307 /* Wait for AEN to change device-state */
4308 qla83xx_idc_unlock(base_vha, 0);
4309 msleep(1000);
4310 qla83xx_idc_lock(base_vha, 0);
4311 }
4312 break;
4313 case QLA8XXX_DEV_INITIALIZING:
4314 /* Wait for AEN to change device-state */
4315 qla83xx_idc_unlock(base_vha, 0);
4316 msleep(1000);
4317 qla83xx_idc_lock(base_vha, 0);
4318 break;
4319 case QLA8XXX_DEV_NEED_RESET:
4320 if (!ql2xdontresethba && ha->flags.nic_core_reset_owner)
4321 qla83xx_need_reset_handler(base_vha);
4322 else {
4323 /* Wait for AEN to change device-state */
4324 qla83xx_idc_unlock(base_vha, 0);
4325 msleep(1000);
4326 qla83xx_idc_lock(base_vha, 0);
4327 }
4328 /* reset timeout value after need reset handler */
4329 dev_init_timeout = jiffies +
4330 (ha->fcoe_dev_init_timeout * HZ);
4331 break;
4332 case QLA8XXX_DEV_NEED_QUIESCENT:
4333 /* XXX: DEBUG for now */
4334 qla83xx_idc_unlock(base_vha, 0);
4335 msleep(1000);
4336 qla83xx_idc_lock(base_vha, 0);
4337 break;
4338 case QLA8XXX_DEV_QUIESCENT:
4339 /* XXX: DEBUG for now */
4340 if (ha->flags.quiesce_owner)
4341 goto exit;
4342
4343 qla83xx_idc_unlock(base_vha, 0);
4344 msleep(1000);
4345 qla83xx_idc_lock(base_vha, 0);
4346 dev_init_timeout = jiffies +
4347 (ha->fcoe_dev_init_timeout * HZ);
4348 break;
4349 case QLA8XXX_DEV_FAILED:
4350 if (ha->flags.nic_core_reset_owner)
4351 qla83xx_idc_audit(base_vha,
4352 IDC_AUDIT_COMPLETION);
4353 ha->flags.nic_core_reset_owner = 0;
4354 __qla83xx_clear_drv_presence(base_vha);
4355 qla83xx_idc_unlock(base_vha, 0);
4356 qla8xxx_dev_failed_handler(base_vha);
4357 rval = QLA_FUNCTION_FAILED;
4358 qla83xx_idc_lock(base_vha, 0);
4359 goto exit;
4360 case QLA8XXX_BAD_VALUE:
4361 qla83xx_idc_unlock(base_vha, 0);
4362 msleep(1000);
4363 qla83xx_idc_lock(base_vha, 0);
4364 break;
4365 default:
4366 ql_log(ql_log_warn, base_vha, 0xb071,
4367 "Unknow Device State: %x.\n", dev_state);
4368 qla83xx_idc_unlock(base_vha, 0);
4369 qla8xxx_dev_failed_handler(base_vha);
4370 rval = QLA_FUNCTION_FAILED;
4371 qla83xx_idc_lock(base_vha, 0);
4372 goto exit;
4373 }
4374 }
4375
4376exit:
4377 return rval;
4378}
4379
3712/************************************************************************** 4380/**************************************************************************
3713* qla2x00_do_dpc 4381* qla2x00_do_dpc
3714* This kernel thread is a task that is schedule by the interrupt handler 4382* This kernel thread is a task that is schedule by the interrupt handler
@@ -3764,7 +4432,7 @@ qla2x00_do_dpc(void *data)
3764 &base_vha->dpc_flags)) { 4432 &base_vha->dpc_flags)) {
3765 qla82xx_idc_lock(ha); 4433 qla82xx_idc_lock(ha);
3766 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 4434 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3767 QLA82XX_DEV_FAILED); 4435 QLA8XXX_DEV_FAILED);
3768 qla82xx_idc_unlock(ha); 4436 qla82xx_idc_unlock(ha);
3769 ql_log(ql_log_info, base_vha, 0x4004, 4437 ql_log(ql_log_info, base_vha, 0x4004,
3770 "HW State: FAILED.\n"); 4438 "HW State: FAILED.\n");
@@ -4341,7 +5009,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
4341 qla82xx_idc_lock(ha); 5009 qla82xx_idc_lock(ha);
4342 5010
4343 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 5011 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
4344 QLA82XX_DEV_INITIALIZING); 5012 QLA8XXX_DEV_INITIALIZING);
4345 5013
4346 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, 5014 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION,
4347 QLA82XX_IDC_VERSION); 5015 QLA82XX_IDC_VERSION);
@@ -4365,12 +5033,12 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
4365 "HW State: FAILED.\n"); 5033 "HW State: FAILED.\n");
4366 qla82xx_clear_drv_active(ha); 5034 qla82xx_clear_drv_active(ha);
4367 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 5035 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
4368 QLA82XX_DEV_FAILED); 5036 QLA8XXX_DEV_FAILED);
4369 } else { 5037 } else {
4370 ql_log(ql_log_info, base_vha, 0x900c, 5038 ql_log(ql_log_info, base_vha, 0x900c,
4371 "HW State: READY.\n"); 5039 "HW State: READY.\n");
4372 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, 5040 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
4373 QLA82XX_DEV_READY); 5041 QLA8XXX_DEV_READY);
4374 qla82xx_idc_unlock(ha); 5042 qla82xx_idc_unlock(ha);
4375 ha->flags.isp82xx_fw_hung = 0; 5043 ha->flags.isp82xx_fw_hung = 0;
4376 rval = qla82xx_restart_isp(base_vha); 5044 rval = qla82xx_restart_isp(base_vha);
@@ -4385,7 +5053,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
4385 "This devfn is not reset owner = 0x%x.\n", 5053 "This devfn is not reset owner = 0x%x.\n",
4386 ha->pdev->devfn); 5054 ha->pdev->devfn);
4387 if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == 5055 if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
4388 QLA82XX_DEV_READY)) { 5056 QLA8XXX_DEV_READY)) {
4389 ha->flags.isp82xx_fw_hung = 0; 5057 ha->flags.isp82xx_fw_hung = 0;
4390 rval = qla82xx_restart_isp(base_vha); 5058 rval = qla82xx_restart_isp(base_vha);
4391 qla82xx_idc_lock(ha); 5059 qla82xx_idc_lock(ha);