diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 4916847d84ec..089e0f500363 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -756,7 +756,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) if (ret == SUCCESS) { if (fcport->flags & FC_FABRIC_DEVICE) { ha->isp_ops.fabric_logout(ha, fcport->loop_id); - qla2x00_mark_device_lost(ha, fcport); + qla2x00_mark_device_lost(ha, fcport, 0, 0); } } #endif @@ -1642,6 +1642,31 @@ qla2x00_free_device(scsi_qla_host_t *ha) pci_disable_device(ha->pdev); } +static inline void +qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, + int defer) +{ + unsigned long flags; + struct fc_rport *rport; + + if (!fcport->rport) + return; + + rport = fcport->rport; + if (defer) { + spin_lock_irqsave(&fcport->rport_lock, flags); + fcport->drport = rport; + fcport->rport = NULL; + spin_unlock_irqrestore(&fcport->rport_lock, flags); + set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); + } else { + spin_lock_irqsave(&fcport->rport_lock, flags); + fcport->rport = NULL; + spin_unlock_irqrestore(&fcport->rport_lock, flags); + fc_remote_port_delete(rport); + } +} + /* * qla2x00_mark_device_lost Updates fcport state when device goes offline. * @@ -1652,10 +1677,10 @@ qla2x00_free_device(scsi_qla_host_t *ha) * Context: */ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, - int do_login) + int do_login, int defer) { - if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) - schedule_work(&fcport->rport_del_work); + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_schedule_rport_del(ha, fcport, defer); /* * We may need to retry the login, so don't change the state of the @@ -1702,7 +1727,7 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, * Context: */ void -qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) +qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) { fc_port_t *fcport; @@ -1716,10 +1741,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) */ if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) continue; - if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) - schedule_work(&fcport->rport_del_work); + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_schedule_rport_del(ha, fcport, defer); atomic_set(&fcport->state, FCS_DEVICE_LOST); } + + if (defer && ha->dpc_wait && !ha->dpc_active) + up(ha->dpc_wait); } /* @@ -2161,6 +2189,9 @@ qla2x00_do_dpc(void *data) ha->host_no)); } + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags)) + qla2x00_update_fcports(ha); + if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) { DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n", ha->host_no)); @@ -2469,6 +2500,7 @@ qla2x00_timer(scsi_qla_host_t *ha) if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) || + test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) || start_dpc || test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || |