aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandrew.vasquez@qlogic.com <andrew.vasquez@qlogic.com>2006-01-20 17:53:13 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2006-01-26 08:16:50 -0500
commitd97994dc1fddcbb8212b745d9c9c9ce96262155c (patch)
tree860d0034485f06dc8cb52c23efb6fe5252a25c99
parent1d12d98d284665c37b75b9538916b5fbb8fcde37 (diff)
[SCSI] qla2xxx: Correct synchronization issues during rport addition/deletion.
The driver can typically detect port-loss during an interrupt context (i.e. via interrogation of a status IOCB's completion status [CS_PORT_LOGGED_OUT]. Due to the calling requirements of the fc_rport APIs, the driver would defer removal of the device to the default workqueue. If the work-item was preceded by an event which caused the port to obtain visibility (relogin successful, target re-logged into the topology), deferred removal could inadvertently drop the rport. The code also no longer defers removal via the default workqueue, instead opting for use of the driver's own DPC thread. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c54
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c46
5 files changed, 91 insertions, 34 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 79d8a914f9d0..bad066e5772a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1680,7 +1680,8 @@ typedef struct fc_port {
1680 uint8_t mp_byte; /* multi-path byte (not used) */ 1680 uint8_t mp_byte; /* multi-path byte (not used) */
1681 uint8_t cur_path; /* current path id */ 1681 uint8_t cur_path; /* current path id */
1682 1682
1683 struct fc_rport *rport; 1683 spinlock_t rport_lock;
1684 struct fc_rport *rport, *drport;
1684 u32 supported_classes; 1685 u32 supported_classes;
1685 struct work_struct rport_add_work; 1686 struct work_struct rport_add_work;
1686 struct work_struct rport_del_work; 1687 struct work_struct rport_del_work;
@@ -2270,6 +2271,7 @@ typedef struct scsi_qla_host {
2270#define LOOP_RESET_NEEDED 24 2271#define LOOP_RESET_NEEDED 24
2271#define BEACON_BLINK_NEEDED 25 2272#define BEACON_BLINK_NEEDED 25
2272#define REGISTER_FDMI_NEEDED 26 2273#define REGISTER_FDMI_NEEDED 26
2274#define FCPORT_UPDATE_NEEDED 27
2273 2275
2274 uint32_t device_flags; 2276 uint32_t device_flags;
2275#define DFLG_LOCAL_DEVICES BIT_0 2277#define DFLG_LOCAL_DEVICES BIT_0
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 32be4c14cccb..0c1ec14f3072 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -47,6 +47,7 @@ extern int qla2x00_local_device_login(scsi_qla_host_t *, uint16_t);
47extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t); 47extern void qla2x00_restart_queues(scsi_qla_host_t *, uint8_t);
48 48
49extern void qla2x00_rescan_fcports(scsi_qla_host_t *); 49extern void qla2x00_rescan_fcports(scsi_qla_host_t *);
50extern void qla2x00_update_fcports(scsi_qla_host_t *);
50 51
51extern int qla2x00_abort_isp(scsi_qla_host_t *); 52extern int qla2x00_abort_isp(scsi_qla_host_t *);
52 53
@@ -70,8 +71,8 @@ extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
70 71
71extern void qla2x00_cmd_timeout(srb_t *); 72extern void qla2x00_cmd_timeout(srb_t *);
72 73
73extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int); 74extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
74extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *); 75extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
75 76
76extern void qla2x00_blink_led(scsi_qla_host_t *); 77extern void qla2x00_blink_led(scsi_qla_host_t *);
77 78
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a91fea69ad63..4c7caece4ca7 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1688,10 +1688,16 @@ static void
1688qla2x00_rport_del(void *data) 1688qla2x00_rport_del(void *data)
1689{ 1689{
1690 fc_port_t *fcport = data; 1690 fc_port_t *fcport = data;
1691 struct fc_rport *rport;
1692 unsigned long flags;
1693
1694 spin_lock_irqsave(&fcport->rport_lock, flags);
1695 rport = fcport->drport;
1696 fcport->drport = NULL;
1697 spin_unlock_irqrestore(&fcport->rport_lock, flags);
1698 if (rport)
1699 fc_remote_port_delete(rport);
1691 1700
1692 if (fcport->rport)
1693 fc_remote_port_delete(fcport->rport);
1694 fcport->rport = NULL;
1695} 1701}
1696 1702
1697/** 1703/**
@@ -1719,6 +1725,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
1719 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1725 atomic_set(&fcport->state, FCS_UNCONFIGURED);
1720 fcport->flags = FCF_RLC_SUPPORT; 1726 fcport->flags = FCF_RLC_SUPPORT;
1721 fcport->supported_classes = FC_COS_UNSPECIFIED; 1727 fcport->supported_classes = FC_COS_UNSPECIFIED;
1728 spin_lock_init(&fcport->rport_lock);
1722 INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport); 1729 INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
1723 INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport); 1730 INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
1724 1731
@@ -2008,7 +2015,7 @@ qla2x00_probe_for_all_luns(scsi_qla_host_t *ha)
2008{ 2015{
2009 fc_port_t *fcport; 2016 fc_port_t *fcport;
2010 2017
2011 qla2x00_mark_all_devices_lost(ha); 2018 qla2x00_mark_all_devices_lost(ha, 0);
2012 list_for_each_entry(fcport, &ha->fcports, list) { 2019 list_for_each_entry(fcport, &ha->fcports, list) {
2013 if (fcport->port_type != FCT_TARGET) 2020 if (fcport->port_type != FCT_TARGET)
2014 continue; 2021 continue;
@@ -2084,24 +2091,29 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
2084{ 2091{
2085 struct fc_rport_identifiers rport_ids; 2092 struct fc_rport_identifiers rport_ids;
2086 struct fc_rport *rport; 2093 struct fc_rport *rport;
2094 unsigned long flags;
2087 2095
2088 if (fcport->rport) { 2096 if (fcport->drport)
2089 fc_remote_port_delete(fcport->rport); 2097 qla2x00_rport_del(fcport);
2090 fcport->rport = NULL; 2098 if (fcport->rport)
2091 } 2099 return;
2092 2100
2093 rport_ids.node_name = wwn_to_u64(fcport->node_name); 2101 rport_ids.node_name = wwn_to_u64(fcport->node_name);
2094 rport_ids.port_name = wwn_to_u64(fcport->port_name); 2102 rport_ids.port_name = wwn_to_u64(fcport->port_name);
2095 rport_ids.port_id = fcport->d_id.b.domain << 16 | 2103 rport_ids.port_id = fcport->d_id.b.domain << 16 |
2096 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; 2104 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
2097 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2105 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
2098 fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); 2106 rport = fc_remote_port_add(ha->host, 0, &rport_ids);
2099 if (!rport) { 2107 if (!rport) {
2100 qla_printk(KERN_WARNING, ha, 2108 qla_printk(KERN_WARNING, ha,
2101 "Unable to allocate fc remote port!\n"); 2109 "Unable to allocate fc remote port!\n");
2102 return; 2110 return;
2103 } 2111 }
2112 spin_lock_irqsave(&fcport->rport_lock, flags);
2113 fcport->rport = rport;
2104 *((fc_port_t **)rport->dd_data) = fcport; 2114 *((fc_port_t **)rport->dd_data) = fcport;
2115 spin_unlock_irqrestore(&fcport->rport_lock, flags);
2116
2105 rport->supported_classes = fcport->supported_classes; 2117 rport->supported_classes = fcport->supported_classes;
2106 2118
2107 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2119 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
@@ -2217,12 +2229,11 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
2217 2229
2218 if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) { 2230 if (atomic_read(&fcport->state) == FCS_DEVICE_LOST) {
2219 qla2x00_mark_device_lost(ha, fcport, 2231 qla2x00_mark_device_lost(ha, fcport,
2220 ql2xplogiabsentdevice); 2232 ql2xplogiabsentdevice, 0);
2221 if (fcport->loop_id != FC_NO_LOOP_ID && 2233 if (fcport->loop_id != FC_NO_LOOP_ID &&
2222 (fcport->flags & FCF_TAPE_PRESENT) == 0 && 2234 (fcport->flags & FCF_TAPE_PRESENT) == 0 &&
2223 fcport->port_type != FCT_INITIATOR && 2235 fcport->port_type != FCT_INITIATOR &&
2224 fcport->port_type != FCT_BROADCAST) { 2236 fcport->port_type != FCT_BROADCAST) {
2225
2226 ha->isp_ops.fabric_logout(ha, 2237 ha->isp_ops.fabric_logout(ha,
2227 fcport->loop_id, 2238 fcport->loop_id,
2228 fcport->d_id.b.domain, 2239 fcport->d_id.b.domain,
@@ -2694,7 +2705,8 @@ qla2x00_device_resync(scsi_qla_host_t *ha)
2694 if (atomic_read(&fcport->state) == FCS_ONLINE) { 2705 if (atomic_read(&fcport->state) == FCS_ONLINE) {
2695 if (format != 3 || 2706 if (format != 3 ||
2696 fcport->port_type != FCT_INITIATOR) { 2707 fcport->port_type != FCT_INITIATOR) {
2697 qla2x00_mark_device_lost(ha, fcport, 0); 2708 qla2x00_mark_device_lost(ha, fcport,
2709 0, 0);
2698 } 2710 }
2699 } 2711 }
2700 fcport->flags &= ~FCF_FARP_DONE; 2712 fcport->flags &= ~FCF_FARP_DONE;
@@ -2741,8 +2753,7 @@ qla2x00_fabric_dev_login(scsi_qla_host_t *ha, fc_port_t *fcport,
2741 ha->isp_ops.fabric_logout(ha, fcport->loop_id, 2753 ha->isp_ops.fabric_logout(ha, fcport->loop_id,
2742 fcport->d_id.b.domain, fcport->d_id.b.area, 2754 fcport->d_id.b.domain, fcport->d_id.b.area,
2743 fcport->d_id.b.al_pa); 2755 fcport->d_id.b.al_pa);
2744 qla2x00_mark_device_lost(ha, fcport, 1); 2756 qla2x00_mark_device_lost(ha, fcport, 1, 0);
2745
2746 } else { 2757 } else {
2747 qla2x00_update_fcport(ha, fcport); 2758 qla2x00_update_fcport(ha, fcport);
2748 } 2759 }
@@ -2855,7 +2866,7 @@ qla2x00_fabric_login(scsi_qla_host_t *ha, fc_port_t *fcport,
2855 ha->isp_ops.fabric_logout(ha, fcport->loop_id, 2866 ha->isp_ops.fabric_logout(ha, fcport->loop_id,
2856 fcport->d_id.b.domain, fcport->d_id.b.area, 2867 fcport->d_id.b.domain, fcport->d_id.b.area,
2857 fcport->d_id.b.al_pa); 2868 fcport->d_id.b.al_pa);
2858 qla2x00_mark_device_lost(ha, fcport, 1); 2869 qla2x00_mark_device_lost(ha, fcport, 1, 0);
2859 2870
2860 rval = 1; 2871 rval = 1;
2861 break; 2872 break;
@@ -2990,6 +3001,17 @@ qla2x00_rescan_fcports(scsi_qla_host_t *ha)
2990 qla2x00_probe_for_all_luns(ha); 3001 qla2x00_probe_for_all_luns(ha);
2991} 3002}
2992 3003
3004void
3005qla2x00_update_fcports(scsi_qla_host_t *ha)
3006{
3007 fc_port_t *fcport;
3008
3009 /* Go with deferred removal of rport references. */
3010 list_for_each_entry(fcport, &ha->fcports, list)
3011 if (fcport->drport)
3012 qla2x00_rport_del(fcport);
3013}
3014
2993/* 3015/*
2994* qla2x00_abort_isp 3016* qla2x00_abort_isp
2995* Resets ISP and aborts all outstanding commands. 3017* Resets ISP and aborts all outstanding commands.
@@ -3019,7 +3041,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
3019 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); 3041 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
3020 if (atomic_read(&ha->loop_state) != LOOP_DOWN) { 3042 if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
3021 atomic_set(&ha->loop_state, LOOP_DOWN); 3043 atomic_set(&ha->loop_state, LOOP_DOWN);
3022 qla2x00_mark_all_devices_lost(ha); 3044 qla2x00_mark_all_devices_lost(ha, 0);
3023 } else { 3045 } else {
3024 if (!atomic_read(&ha->loop_down_timer)) 3046 if (!atomic_read(&ha->loop_down_timer))
3025 atomic_set(&ha->loop_down_timer, 3047 atomic_set(&ha->loop_down_timer,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f63af081d4ff..71a46fcee8cc 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -389,7 +389,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
389 if (atomic_read(&ha->loop_state) != LOOP_DOWN) { 389 if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
390 atomic_set(&ha->loop_state, LOOP_DOWN); 390 atomic_set(&ha->loop_state, LOOP_DOWN);
391 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); 391 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
392 qla2x00_mark_all_devices_lost(ha); 392 qla2x00_mark_all_devices_lost(ha, 1);
393 } 393 }
394 394
395 set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags); 395 set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
@@ -432,7 +432,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
432 atomic_set(&ha->loop_state, LOOP_DOWN); 432 atomic_set(&ha->loop_state, LOOP_DOWN);
433 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); 433 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
434 ha->device_flags |= DFLG_NO_CABLE; 434 ha->device_flags |= DFLG_NO_CABLE;
435 qla2x00_mark_all_devices_lost(ha); 435 qla2x00_mark_all_devices_lost(ha, 1);
436 } 436 }
437 437
438 ha->flags.management_server_logged_in = 0; 438 ha->flags.management_server_logged_in = 0;
@@ -453,7 +453,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
453 if (atomic_read(&ha->loop_state) != LOOP_DOWN) { 453 if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
454 atomic_set(&ha->loop_state, LOOP_DOWN); 454 atomic_set(&ha->loop_state, LOOP_DOWN);
455 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME); 455 atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
456 qla2x00_mark_all_devices_lost(ha); 456 qla2x00_mark_all_devices_lost(ha, 1);
457 } 457 }
458 458
459 set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); 459 set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
@@ -482,7 +482,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
482 if (!atomic_read(&ha->loop_down_timer)) 482 if (!atomic_read(&ha->loop_down_timer))
483 atomic_set(&ha->loop_down_timer, 483 atomic_set(&ha->loop_down_timer,
484 LOOP_DOWN_TIME); 484 LOOP_DOWN_TIME);
485 qla2x00_mark_all_devices_lost(ha); 485 qla2x00_mark_all_devices_lost(ha, 1);
486 } 486 }
487 487
488 if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) { 488 if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags))) {
@@ -506,7 +506,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
506 if (!atomic_read(&ha->loop_down_timer)) 506 if (!atomic_read(&ha->loop_down_timer))
507 atomic_set(&ha->loop_down_timer, 507 atomic_set(&ha->loop_down_timer,
508 LOOP_DOWN_TIME); 508 LOOP_DOWN_TIME);
509 qla2x00_mark_all_devices_lost(ha); 509 qla2x00_mark_all_devices_lost(ha, 1);
510 } 510 }
511 511
512 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); 512 set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
@@ -580,7 +580,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
580 */ 580 */
581 atomic_set(&ha->loop_state, LOOP_UP); 581 atomic_set(&ha->loop_state, LOOP_UP);
582 582
583 qla2x00_mark_all_devices_lost(ha); 583 qla2x00_mark_all_devices_lost(ha, 1);
584 584
585 ha->flags.rscn_queue_overflow = 1; 585 ha->flags.rscn_queue_overflow = 1;
586 586
@@ -1091,7 +1091,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
1091 1091
1092 cp->result = DID_BUS_BUSY << 16; 1092 cp->result = DID_BUS_BUSY << 16;
1093 if (atomic_read(&fcport->state) == FCS_ONLINE) { 1093 if (atomic_read(&fcport->state) == FCS_ONLINE) {
1094 qla2x00_mark_device_lost(ha, fcport, 1); 1094 qla2x00_mark_device_lost(ha, fcport, 1, 1);
1095 } 1095 }
1096 break; 1096 break;
1097 1097
@@ -1135,7 +1135,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
1135 1135
1136 /* Check to see if logout occurred. */ 1136 /* Check to see if logout occurred. */
1137 if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) 1137 if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT))
1138 qla2x00_mark_device_lost(ha, fcport, 1); 1138 qla2x00_mark_device_lost(ha, fcport, 1, 1);
1139 break; 1139 break;
1140 1140
1141 case CS_QUEUE_FULL: 1141 case CS_QUEUE_FULL:
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)
756 if (ret == SUCCESS) { 756 if (ret == SUCCESS) {
757 if (fcport->flags & FC_FABRIC_DEVICE) { 757 if (fcport->flags & FC_FABRIC_DEVICE) {
758 ha->isp_ops.fabric_logout(ha, fcport->loop_id); 758 ha->isp_ops.fabric_logout(ha, fcport->loop_id);
759 qla2x00_mark_device_lost(ha, fcport); 759 qla2x00_mark_device_lost(ha, fcport, 0, 0);
760 } 760 }
761 } 761 }
762#endif 762#endif
@@ -1642,6 +1642,31 @@ qla2x00_free_device(scsi_qla_host_t *ha)
1642 pci_disable_device(ha->pdev); 1642 pci_disable_device(ha->pdev);
1643} 1643}
1644 1644
1645static inline void
1646qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
1647 int defer)
1648{
1649 unsigned long flags;
1650 struct fc_rport *rport;
1651
1652 if (!fcport->rport)
1653 return;
1654
1655 rport = fcport->rport;
1656 if (defer) {
1657 spin_lock_irqsave(&fcport->rport_lock, flags);
1658 fcport->drport = rport;
1659 fcport->rport = NULL;
1660 spin_unlock_irqrestore(&fcport->rport_lock, flags);
1661 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
1662 } else {
1663 spin_lock_irqsave(&fcport->rport_lock, flags);
1664 fcport->rport = NULL;
1665 spin_unlock_irqrestore(&fcport->rport_lock, flags);
1666 fc_remote_port_delete(rport);
1667 }
1668}
1669
1645/* 1670/*
1646 * qla2x00_mark_device_lost Updates fcport state when device goes offline. 1671 * qla2x00_mark_device_lost Updates fcport state when device goes offline.
1647 * 1672 *
@@ -1652,10 +1677,10 @@ qla2x00_free_device(scsi_qla_host_t *ha)
1652 * Context: 1677 * Context:
1653 */ 1678 */
1654void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, 1679void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
1655 int do_login) 1680 int do_login, int defer)
1656{ 1681{
1657 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) 1682 if (atomic_read(&fcport->state) == FCS_ONLINE)
1658 schedule_work(&fcport->rport_del_work); 1683 qla2x00_schedule_rport_del(ha, fcport, defer);
1659 1684
1660 /* 1685 /*
1661 * We may need to retry the login, so don't change the state of the 1686 * 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,
1702 * Context: 1727 * Context:
1703 */ 1728 */
1704void 1729void
1705qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha) 1730qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer)
1706{ 1731{
1707 fc_port_t *fcport; 1732 fc_port_t *fcport;
1708 1733
@@ -1716,10 +1741,13 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
1716 */ 1741 */
1717 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) 1742 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
1718 continue; 1743 continue;
1719 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) 1744 if (atomic_read(&fcport->state) == FCS_ONLINE)
1720 schedule_work(&fcport->rport_del_work); 1745 qla2x00_schedule_rport_del(ha, fcport, defer);
1721 atomic_set(&fcport->state, FCS_DEVICE_LOST); 1746 atomic_set(&fcport->state, FCS_DEVICE_LOST);
1722 } 1747 }
1748
1749 if (defer && ha->dpc_wait && !ha->dpc_active)
1750 up(ha->dpc_wait);
1723} 1751}
1724 1752
1725/* 1753/*
@@ -2161,6 +2189,9 @@ qla2x00_do_dpc(void *data)
2161 ha->host_no)); 2189 ha->host_no));
2162 } 2190 }
2163 2191
2192 if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags))
2193 qla2x00_update_fcports(ha);
2194
2164 if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) { 2195 if (test_and_clear_bit(LOOP_RESET_NEEDED, &ha->dpc_flags)) {
2165 DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n", 2196 DEBUG(printk("scsi(%ld): dpc: sched loop_reset()\n",
2166 ha->host_no)); 2197 ha->host_no));
@@ -2469,6 +2500,7 @@ qla2x00_timer(scsi_qla_host_t *ha)
2469 if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) || 2500 if ((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags) ||
2470 test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || 2501 test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) ||
2471 test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) || 2502 test_bit(LOOP_RESET_NEEDED, &ha->dpc_flags) ||
2503 test_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags) ||
2472 start_dpc || 2504 start_dpc ||
2473 test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || 2505 test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) ||
2474 test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || 2506 test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) ||