aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c67
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c132
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c24
5 files changed, 224 insertions, 6 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 9ce539d4557..6168628bd6b 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2425,6 +2425,8 @@ struct qla_hw_data {
2425 uint32_t disable_msix_handshake :1; 2425 uint32_t disable_msix_handshake :1;
2426 uint32_t fcp_prio_enabled :1; 2426 uint32_t fcp_prio_enabled :1;
2427 uint32_t fw_hung :1; 2427 uint32_t fw_hung :1;
2428 uint32_t quiesce_owner:1;
2429 /* 29 bits */
2428 } flags; 2430 } flags;
2429 2431
2430 /* This spinlock is used to protect "io transactions", you must 2432 /* This spinlock is used to protect "io transactions", you must
@@ -2863,6 +2865,7 @@ typedef struct scsi_qla_host {
2863#define ISP_UNRECOVERABLE 17 2865#define ISP_UNRECOVERABLE 17
2864#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */ 2866#define FCOE_CTX_RESET_NEEDED 18 /* Initiate FCoE context reset */
2865#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */ 2867#define MPI_RESET_NEEDED 19 /* Initiate MPI FW reset */
2868#define ISP_QUIESCE_NEEDED 20 /* Driver need some quiescence */
2866 2869
2867 uint32_t device_flags; 2870 uint32_t device_flags;
2868#define SWITCH_FOUND BIT_0 2871#define SWITCH_FOUND BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9382a816c13..1370f05ae33 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -36,6 +36,7 @@ extern int qla2x00_load_risc(struct scsi_qla_host *, uint32_t *);
36extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *); 36extern int qla24xx_load_risc(scsi_qla_host_t *, uint32_t *);
37extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *); 37extern int qla81xx_load_risc(scsi_qla_host_t *, uint32_t *);
38 38
39extern int qla2x00_perform_loop_resync(scsi_qla_host_t *);
39extern int qla2x00_loop_resync(scsi_qla_host_t *); 40extern int qla2x00_loop_resync(scsi_qla_host_t *);
40 41
41extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *); 42extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
@@ -45,6 +46,7 @@ extern void qla2x00_update_fcports(scsi_qla_host_t *);
45 46
46extern int qla2x00_abort_isp(scsi_qla_host_t *); 47extern int qla2x00_abort_isp(scsi_qla_host_t *);
47extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *); 48extern void qla2x00_abort_isp_cleanup(scsi_qla_host_t *);
49extern void qla82xx_quiescent_state_cleanup(scsi_qla_host_t *);
48 50
49extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); 51extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *);
50 52
@@ -549,9 +551,11 @@ extern void qla82xx_rom_unlock(struct qla_hw_data *);
549 551
550/* ISP 8021 IDC */ 552/* ISP 8021 IDC */
551extern void qla82xx_clear_drv_active(struct qla_hw_data *); 553extern void qla82xx_clear_drv_active(struct qla_hw_data *);
554extern uint32_t qla82xx_wait_for_state_change(scsi_qla_host_t *, uint32_t);
552extern int qla82xx_idc_lock(struct qla_hw_data *); 555extern int qla82xx_idc_lock(struct qla_hw_data *);
553extern void qla82xx_idc_unlock(struct qla_hw_data *); 556extern void qla82xx_idc_unlock(struct qla_hw_data *);
554extern int qla82xx_device_state_handler(scsi_qla_host_t *); 557extern int qla82xx_device_state_handler(scsi_qla_host_t *);
558extern void qla82xx_clear_qsnt_ready(scsi_qla_host_t *);
555 559
556extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *, 560extern void qla2x00_set_model_info(scsi_qla_host_t *, uint8_t *,
557 size_t, char *); 561 size_t, char *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 259f5113749..6f7cf397038 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3844,6 +3844,37 @@ qla2x00_loop_resync(scsi_qla_host_t *vha)
3844 return (rval); 3844 return (rval);
3845} 3845}
3846 3846
3847/*
3848* qla2x00_perform_loop_resync
3849* Description: This function will set the appropriate flags and call
3850* qla2x00_loop_resync. If successful loop will be resynced
3851* Arguments : scsi_qla_host_t pointer
3852* returm : Success or Failure
3853*/
3854
3855int qla2x00_perform_loop_resync(scsi_qla_host_t *ha)
3856{
3857 int32_t rval = 0;
3858
3859 if (!test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags)) {
3860 /*Configure the flags so that resync happens properly*/
3861 atomic_set(&ha->loop_down_timer, 0);
3862 if (!(ha->device_flags & DFLG_NO_CABLE)) {
3863 atomic_set(&ha->loop_state, LOOP_UP);
3864 set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
3865 set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
3866 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
3867
3868 rval = qla2x00_loop_resync(ha);
3869 } else
3870 atomic_set(&ha->loop_state, LOOP_DEAD);
3871
3872 clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags);
3873 }
3874
3875 return rval;
3876}
3877
3847void 3878void
3848qla2x00_update_fcports(scsi_qla_host_t *base_vha) 3879qla2x00_update_fcports(scsi_qla_host_t *base_vha)
3849{ 3880{
@@ -3871,11 +3902,43 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
3871 spin_unlock_irqrestore(&ha->vport_slock, flags); 3902 spin_unlock_irqrestore(&ha->vport_slock, flags);
3872} 3903}
3873 3904
3905/*
3906* qla82xx_quiescent_state_cleanup
3907* Description: This function will block the new I/Os
3908* Its not aborting any I/Os as context
3909* is not destroyed during quiescence
3910* Arguments: scsi_qla_host_t
3911* return : void
3912*/
3913void
3914qla82xx_quiescent_state_cleanup(scsi_qla_host_t *vha)
3915{
3916 struct qla_hw_data *ha = vha->hw;
3917 struct scsi_qla_host *vp;
3918
3919 qla_printk(KERN_INFO, ha,
3920 "Performing ISP error recovery - ha= %p.\n", ha);
3921
3922 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
3923 if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
3924 atomic_set(&vha->loop_state, LOOP_DOWN);
3925 qla2x00_mark_all_devices_lost(vha, 0);
3926 list_for_each_entry(vp, &ha->vp_list, list)
3927 qla2x00_mark_all_devices_lost(vha, 0);
3928 } else {
3929 if (!atomic_read(&vha->loop_down_timer))
3930 atomic_set(&vha->loop_down_timer,
3931 LOOP_DOWN_TIME);
3932 }
3933 /* Wait for pending cmds to complete */
3934 qla2x00_eh_wait_for_pending_commands(vha, 0, 0, WAIT_HOST);
3935}
3936
3874void 3937void
3875qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha) 3938qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
3876{ 3939{
3877 struct qla_hw_data *ha = vha->hw; 3940 struct qla_hw_data *ha = vha->hw;
3878 struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); 3941 struct scsi_qla_host *vp;
3879 unsigned long flags; 3942 unsigned long flags;
3880 3943
3881 vha->flags.online = 0; 3944 vha->flags.online = 0;
@@ -3896,7 +3959,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
3896 qla2x00_mark_all_devices_lost(vha, 0); 3959 qla2x00_mark_all_devices_lost(vha, 0);
3897 3960
3898 spin_lock_irqsave(&ha->vport_slock, flags); 3961 spin_lock_irqsave(&ha->vport_slock, flags);
3899 list_for_each_entry(vp, &base_vha->hw->vp_list, list) { 3962 list_for_each_entry(vp, &ha->vp_list, list) {
3900 atomic_inc(&vp->vref_count); 3963 atomic_inc(&vp->vref_count);
3901 spin_unlock_irqrestore(&ha->vport_slock, flags); 3964 spin_unlock_irqrestore(&ha->vport_slock, flags);
3902 3965
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index ae2acacc000..9175e847b93 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -2343,6 +2343,17 @@ qla82xx_set_qsnt_ready(struct qla_hw_data *ha)
2343 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state); 2343 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
2344} 2344}
2345 2345
2346void
2347qla82xx_clear_qsnt_ready(scsi_qla_host_t *vha)
2348{
2349 struct qla_hw_data *ha = vha->hw;
2350 uint32_t qsnt_state;
2351
2352 qsnt_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
2353 qsnt_state &= ~(QLA82XX_DRVST_QSNT_RDY << (ha->portnum * 4));
2354 qla82xx_wr_32(ha, QLA82XX_CRB_DRV_STATE, qsnt_state);
2355}
2356
2346static int 2357static int
2347qla82xx_load_fw(scsi_qla_host_t *vha) 2358qla82xx_load_fw(scsi_qla_host_t *vha)
2348{ 2359{
@@ -3261,6 +3272,104 @@ dev_ready:
3261 return QLA_SUCCESS; 3272 return QLA_SUCCESS;
3262} 3273}
3263 3274
3275/*
3276* qla82xx_need_qsnt_handler
3277* Code to start quiescence sequence
3278*
3279* Note:
3280* IDC lock must be held upon entry
3281*
3282* Return: void
3283*/
3284
3285static void
3286qla82xx_need_qsnt_handler(scsi_qla_host_t *vha)
3287{
3288 struct qla_hw_data *ha = vha->hw;
3289 uint32_t dev_state, drv_state, drv_active;
3290 unsigned long reset_timeout;
3291
3292 if (vha->flags.online) {
3293 /*Block any further I/O and wait for pending cmnds to complete*/
3294 qla82xx_quiescent_state_cleanup(vha);
3295 }
3296
3297 /* Set the quiescence ready bit */
3298 qla82xx_set_qsnt_ready(ha);
3299
3300 /*wait for 30 secs for other functions to ack */
3301 reset_timeout = jiffies + (30 * HZ);
3302
3303 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
3304 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
3305 /* Its 2 that is written when qsnt is acked, moving one bit */
3306 drv_active = drv_active << 0x01;
3307
3308 while (drv_state != drv_active) {
3309
3310 if (time_after_eq(jiffies, reset_timeout)) {
3311 /* quiescence timeout, other functions didn't ack
3312 * changing the state to DEV_READY
3313 */
3314 qla_printk(KERN_INFO, ha,
3315 "%s: QUIESCENT TIMEOUT\n", QLA2XXX_DRIVER_NAME);
3316 qla_printk(KERN_INFO, ha,
3317 "DRV_ACTIVE:%d DRV_STATE:%d\n", drv_active,
3318 drv_state);
3319 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
3320 QLA82XX_DEV_READY);
3321 qla_printk(KERN_INFO, ha,
3322 "HW State: DEV_READY\n");
3323 qla82xx_idc_unlock(ha);
3324 qla2x00_perform_loop_resync(vha);
3325 qla82xx_idc_lock(ha);
3326
3327 qla82xx_clear_qsnt_ready(vha);
3328 return;
3329 }
3330
3331 qla82xx_idc_unlock(ha);
3332 msleep(1000);
3333 qla82xx_idc_lock(ha);
3334
3335 drv_state = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_STATE);
3336 drv_active = qla82xx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE);
3337 drv_active = drv_active << 0x01;
3338 }
3339 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
3340 /* everyone acked so set the state to DEV_QUIESCENCE */
3341 if (dev_state == QLA82XX_DEV_NEED_QUIESCENT) {
3342 qla_printk(KERN_INFO, ha, "HW State: DEV_QUIESCENT\n");
3343 qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_QUIESCENT);
3344 }
3345}
3346
3347/*
3348* qla82xx_wait_for_state_change
3349* Wait for device state to change from given current state
3350*
3351* Note:
3352* IDC lock must not be held upon entry
3353*
3354* Return:
3355* Changed device state.
3356*/
3357uint32_t
3358qla82xx_wait_for_state_change(scsi_qla_host_t *vha, uint32_t curr_state)
3359{
3360 struct qla_hw_data *ha = vha->hw;
3361 uint32_t dev_state;
3362
3363 do {
3364 msleep(1000);
3365 qla82xx_idc_lock(ha);
3366 dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
3367 qla82xx_idc_unlock(ha);
3368 } while (dev_state == curr_state);
3369
3370 return dev_state;
3371}
3372
3264static void 3373static void
3265qla82xx_dev_failed_handler(scsi_qla_host_t *vha) 3374qla82xx_dev_failed_handler(scsi_qla_host_t *vha)
3266{ 3375{
@@ -3443,11 +3552,25 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
3443 qla82xx_need_reset_handler(vha); 3552 qla82xx_need_reset_handler(vha);
3444 break; 3553 break;
3445 case QLA82XX_DEV_NEED_QUIESCENT: 3554 case QLA82XX_DEV_NEED_QUIESCENT:
3446 qla82xx_set_qsnt_ready(ha); 3555 qla82xx_need_qsnt_handler(vha);
3556 /* Reset timeout value after quiescence handler */
3557 dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
3558 * HZ);
3559 break;
3447 case QLA82XX_DEV_QUIESCENT: 3560 case QLA82XX_DEV_QUIESCENT:
3561 /* Owner will exit and other will wait for the state
3562 * to get changed
3563 */
3564 if (ha->flags.quiesce_owner)
3565 goto exit;
3566
3448 qla82xx_idc_unlock(ha); 3567 qla82xx_idc_unlock(ha);
3449 msleep(1000); 3568 msleep(1000);
3450 qla82xx_idc_lock(ha); 3569 qla82xx_idc_lock(ha);
3570
3571 /* Reset timeout value after quiescence handler */
3572 dev_init_timeout = jiffies + (ha->nx_dev_init_timeout\
3573 * HZ);
3451 break; 3574 break;
3452 case QLA82XX_DEV_FAILED: 3575 case QLA82XX_DEV_FAILED:
3453 qla82xx_dev_failed_handler(vha); 3576 qla82xx_dev_failed_handler(vha);
@@ -3490,6 +3613,13 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
3490 &ha->mbx_cmd_flags)) 3613 &ha->mbx_cmd_flags))
3491 complete(&ha->mbx_intr_comp); 3614 complete(&ha->mbx_intr_comp);
3492 } 3615 }
3616 } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
3617 !test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
3618 DEBUG(qla_printk(KERN_INFO, ha,
3619 "scsi(%ld) %s - detected quiescence needed\n",
3620 vha->host_no, __func__));
3621 set_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags);
3622 qla2xxx_wake_dpc(vha);
3493 } else { 3623 } else {
3494 qla82xx_check_fw_alive(vha); 3624 qla82xx_check_fw_alive(vha);
3495 } 3625 }
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 2c0876c81a3..df2c1e7ab65 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3386,6 +3386,21 @@ qla2x00_do_dpc(void *data)
3386 clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); 3386 clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
3387 } 3387 }
3388 3388
3389 if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) {
3390 DEBUG(printk(KERN_INFO "scsi(%ld): dpc: sched "
3391 "qla2x00_quiesce_needed ha = %p\n",
3392 base_vha->host_no, ha));
3393 qla82xx_device_state_handler(base_vha);
3394 clear_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags);
3395 if (!ha->flags.quiesce_owner) {
3396 qla2x00_perform_loop_resync(base_vha);
3397
3398 qla82xx_idc_lock(ha);
3399 qla82xx_clear_qsnt_ready(base_vha);
3400 qla82xx_idc_unlock(ha);
3401 }
3402 }
3403
3389 if (test_and_clear_bit(RESET_MARKER_NEEDED, 3404 if (test_and_clear_bit(RESET_MARKER_NEEDED,
3390 &base_vha->dpc_flags) && 3405 &base_vha->dpc_flags) &&
3391 (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) { 3406 (!(test_and_set_bit(RESET_ACTIVE, &base_vha->dpc_flags)))) {
@@ -3589,13 +3604,16 @@ qla2x00_timer(scsi_qla_host_t *vha)
3589 return; 3604 return;
3590 } 3605 }
3591 3606
3592 if (IS_QLA82XX(ha))
3593 qla82xx_watchdog(vha);
3594
3595 /* Hardware read to raise pending EEH errors during mailbox waits. */ 3607 /* Hardware read to raise pending EEH errors during mailbox waits. */
3596 if (!pci_channel_offline(ha->pdev)) 3608 if (!pci_channel_offline(ha->pdev))
3597 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); 3609 pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
3598 3610
3611 if (IS_QLA82XX(ha)) {
3612 if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
3613 start_dpc++;
3614 qla82xx_watchdog(vha);
3615 }
3616
3599 /* Loop down handler. */ 3617 /* Loop down handler. */
3600 if (atomic_read(&vha->loop_down_timer) > 0 && 3618 if (atomic_read(&vha->loop_down_timer) > 0 &&
3601 !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) 3619 !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))