aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c31
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h1
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c53
5 files changed, 78 insertions, 25 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 8dd88fc1244a..3112518b0e64 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -994,6 +994,33 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
994 rport->dev_loss_tmo = ha->port_down_retry_count + 5; 994 rport->dev_loss_tmo = ha->port_down_retry_count + 5;
995} 995}
996 996
997static void
998qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
999{
1000 struct Scsi_Host *host = rport_to_shost(rport);
1001 fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1002
1003 qla2x00_abort_fcport_cmds(fcport);
1004
1005 /*
1006 * Transport has effectively 'deleted' the rport, clear
1007 * all local references.
1008 */
1009 spin_lock_irq(host->host_lock);
1010 fcport->rport = NULL;
1011 *((fc_port_t **)rport->dd_data) = NULL;
1012 spin_unlock_irq(host->host_lock);
1013}
1014
1015static void
1016qla2x00_terminate_rport_io(struct fc_rport *rport)
1017{
1018 fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
1019
1020 qla2x00_abort_fcport_cmds(fcport);
1021 scsi_target_unblock(&rport->dev);
1022}
1023
997static int 1024static int
998qla2x00_issue_lip(struct Scsi_Host *shost) 1025qla2x00_issue_lip(struct Scsi_Host *shost)
999{ 1026{
@@ -1253,6 +1280,8 @@ struct fc_function_template qla2xxx_transport_functions = {
1253 .show_rport_dev_loss_tmo = 1, 1280 .show_rport_dev_loss_tmo = 1,
1254 1281
1255 .issue_fc_host_lip = qla2x00_issue_lip, 1282 .issue_fc_host_lip = qla2x00_issue_lip,
1283 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1284 .terminate_rport_io = qla2x00_terminate_rport_io,
1256 .get_fc_host_stats = qla2x00_get_fc_host_stats, 1285 .get_fc_host_stats = qla2x00_get_fc_host_stats,
1257 1286
1258 .vport_create = qla24xx_vport_create, 1287 .vport_create = qla24xx_vport_create,
@@ -1296,6 +1325,8 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
1296 .show_rport_dev_loss_tmo = 1, 1325 .show_rport_dev_loss_tmo = 1,
1297 1326
1298 .issue_fc_host_lip = qla2x00_issue_lip, 1327 .issue_fc_host_lip = qla2x00_issue_lip,
1328 .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk,
1329 .terminate_rport_io = qla2x00_terminate_rport_io,
1299 .get_fc_host_stats = qla2x00_get_fc_host_stats, 1330 .get_fc_host_stats = qla2x00_get_fc_host_stats,
1300}; 1331};
1301 1332
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 8dd600013bd1..7b0ddc83413f 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1544,7 +1544,6 @@ typedef struct fc_port {
1544 int login_retry; 1544 int login_retry;
1545 atomic_t port_down_timer; 1545 atomic_t port_down_timer;
1546 1546
1547 spinlock_t rport_lock;
1548 struct fc_rport *rport, *drport; 1547 struct fc_rport *rport, *drport;
1549 u32 supported_classes; 1548 u32 supported_classes;
1550 1549
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 9b4bebee6879..5a50fb749728 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -71,6 +71,8 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
71extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t, 71extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
72 uint16_t, uint16_t); 72 uint16_t, uint16_t);
73 73
74extern void qla2x00_abort_fcport_cmds(fc_port_t *);
75
74/* 76/*
75 * Global Functions in qla_mid.c source file. 77 * Global Functions in qla_mid.c source file.
76 */ 78 */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index bbbc5a632a1d..c7388fadf225 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1864,12 +1864,11 @@ qla2x00_rport_del(void *data)
1864{ 1864{
1865 fc_port_t *fcport = data; 1865 fc_port_t *fcport = data;
1866 struct fc_rport *rport; 1866 struct fc_rport *rport;
1867 unsigned long flags;
1868 1867
1869 spin_lock_irqsave(&fcport->rport_lock, flags); 1868 spin_lock_irq(fcport->ha->host->host_lock);
1870 rport = fcport->drport; 1869 rport = fcport->drport;
1871 fcport->drport = NULL; 1870 fcport->drport = NULL;
1872 spin_unlock_irqrestore(&fcport->rport_lock, flags); 1871 spin_unlock_irq(fcport->ha->host->host_lock);
1873 if (rport) 1872 if (rport)
1874 fc_remote_port_delete(rport); 1873 fc_remote_port_delete(rport);
1875} 1874}
@@ -1898,7 +1897,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
1898 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1897 atomic_set(&fcport->state, FCS_UNCONFIGURED);
1899 fcport->flags = FCF_RLC_SUPPORT; 1898 fcport->flags = FCF_RLC_SUPPORT;
1900 fcport->supported_classes = FC_COS_UNSPECIFIED; 1899 fcport->supported_classes = FC_COS_UNSPECIFIED;
1901 spin_lock_init(&fcport->rport_lock);
1902 1900
1903 return fcport; 1901 return fcport;
1904} 1902}
@@ -2243,28 +2241,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
2243{ 2241{
2244 struct fc_rport_identifiers rport_ids; 2242 struct fc_rport_identifiers rport_ids;
2245 struct fc_rport *rport; 2243 struct fc_rport *rport;
2246 unsigned long flags;
2247 2244
2248 if (fcport->drport) 2245 if (fcport->drport)
2249 qla2x00_rport_del(fcport); 2246 qla2x00_rport_del(fcport);
2250 if (fcport->rport)
2251 return;
2252 2247
2253 rport_ids.node_name = wwn_to_u64(fcport->node_name); 2248 rport_ids.node_name = wwn_to_u64(fcport->node_name);
2254 rport_ids.port_name = wwn_to_u64(fcport->port_name); 2249 rport_ids.port_name = wwn_to_u64(fcport->port_name);
2255 rport_ids.port_id = fcport->d_id.b.domain << 16 | 2250 rport_ids.port_id = fcport->d_id.b.domain << 16 |
2256 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; 2251 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa;
2257 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2252 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
2258 rport = fc_remote_port_add(ha->host, 0, &rport_ids); 2253 fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids);
2259 if (!rport) { 2254 if (!rport) {
2260 qla_printk(KERN_WARNING, ha, 2255 qla_printk(KERN_WARNING, ha,
2261 "Unable to allocate fc remote port!\n"); 2256 "Unable to allocate fc remote port!\n");
2262 return; 2257 return;
2263 } 2258 }
2264 spin_lock_irqsave(&fcport->rport_lock, flags); 2259 spin_lock_irq(fcport->ha->host->host_lock);
2265 fcport->rport = rport;
2266 *((fc_port_t **)rport->dd_data) = fcport; 2260 *((fc_port_t **)rport->dd_data) = fcport;
2267 spin_unlock_irqrestore(&fcport->rport_lock, flags); 2261 spin_unlock_irq(fcport->ha->host->host_lock);
2268 2262
2269 rport->supported_classes = fcport->supported_classes; 2263 rport->supported_classes = fcport->supported_classes;
2270 2264
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 48eaa3bb5433..c5ad858e17e6 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -388,7 +388,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
388 } 388 }
389 389
390 /* Close window on fcport/rport state-transitioning. */ 390 /* Close window on fcport/rport state-transitioning. */
391 if (!*(fc_port_t **)rport->dd_data) { 391 if (fcport->drport) {
392 cmd->result = DID_IMM_RETRY << 16; 392 cmd->result = DID_IMM_RETRY << 16;
393 goto qc_fail_command; 393 goto qc_fail_command;
394 } 394 }
@@ -455,7 +455,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
455 } 455 }
456 456
457 /* Close window on fcport/rport state-transitioning. */ 457 /* Close window on fcport/rport state-transitioning. */
458 if (!*(fc_port_t **)rport->dd_data) { 458 if (fcport->drport) {
459 cmd->result = DID_IMM_RETRY << 16; 459 cmd->result = DID_IMM_RETRY << 16;
460 goto qc24_fail_command; 460 goto qc24_fail_command;
461 } 461 }
@@ -617,6 +617,40 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
617 return (return_status); 617 return (return_status);
618} 618}
619 619
620void
621qla2x00_abort_fcport_cmds(fc_port_t *fcport)
622{
623 int cnt;
624 unsigned long flags;
625 srb_t *sp;
626 scsi_qla_host_t *ha = fcport->ha;
627 scsi_qla_host_t *pha = to_qla_parent(ha);
628
629 spin_lock_irqsave(&pha->hardware_lock, flags);
630 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
631 sp = pha->outstanding_cmds[cnt];
632 if (!sp)
633 continue;
634 if (sp->fcport != fcport)
635 continue;
636
637 spin_unlock_irqrestore(&pha->hardware_lock, flags);
638 if (ha->isp_ops->abort_command(ha, sp)) {
639 DEBUG2(qla_printk(KERN_WARNING, ha,
640 "Abort failed -- %lx\n", sp->cmd->serial_number));
641 } else {
642 if (qla2x00_eh_wait_on_command(ha, sp->cmd) !=
643 QLA_SUCCESS)
644 DEBUG2(qla_printk(KERN_WARNING, ha,
645 "Abort failed while waiting -- %lx\n",
646 sp->cmd->serial_number));
647
648 }
649 spin_lock_irqsave(&pha->hardware_lock, flags);
650 }
651 spin_unlock_irqrestore(&pha->hardware_lock, flags);
652}
653
620static void 654static void
621qla2x00_block_error_handler(struct scsi_cmnd *cmnd) 655qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
622{ 656{
@@ -1813,7 +1847,6 @@ static inline void
1813qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, 1847qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
1814 int defer) 1848 int defer)
1815{ 1849{
1816 unsigned long flags;
1817 struct fc_rport *rport; 1850 struct fc_rport *rport;
1818 1851
1819 if (!fcport->rport) 1852 if (!fcport->rport)
@@ -1821,19 +1854,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport,
1821 1854
1822 rport = fcport->rport; 1855 rport = fcport->rport;
1823 if (defer) { 1856 if (defer) {
1824 spin_lock_irqsave(&fcport->rport_lock, flags); 1857 spin_lock_irq(ha->host->host_lock);
1825 fcport->drport = rport; 1858 fcport->drport = rport;
1826 fcport->rport = NULL; 1859 spin_unlock_irq(ha->host->host_lock);
1827 *(fc_port_t **)rport->dd_data = NULL;
1828 spin_unlock_irqrestore(&fcport->rport_lock, flags);
1829 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); 1860 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags);
1830 } else { 1861 qla2xxx_wake_dpc(ha);
1831 spin_lock_irqsave(&fcport->rport_lock, flags); 1862 } else
1832 fcport->rport = NULL;
1833 *(fc_port_t **)rport->dd_data = NULL;
1834 spin_unlock_irqrestore(&fcport->rport_lock, flags);
1835 fc_remote_port_delete(rport); 1863 fc_remote_port_delete(rport);
1836 }
1837} 1864}
1838 1865
1839/* 1866/*