From 47668fc2803db3524b852c91dfb7e2cce410fa5d Mon Sep 17 00:00:00 2001 From: Seokmann Ju Date: Thu, 14 Aug 2008 09:37:34 -0700 Subject: qla2xxx: Add dev_loss_tmo_callbk/terminate_rport_io callback support. [ Upstream commit 5f3a9a207f1fccde476dd31b4c63ead2967d934f ] Signed-off-by: Seokmann Ju Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/qla2xxx/qla_attr.c | 31 ++++++++++++++++++++++++ drivers/scsi/qla2xxx/qla_def.h | 1 - drivers/scsi/qla2xxx/qla_gbl.h | 2 ++ drivers/scsi/qla2xxx/qla_init.c | 16 ++++--------- drivers/scsi/qla2xxx/qla_os.c | 53 +++++++++++++++++++++++++++++++---------- 5 files changed, 78 insertions(+), 25 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 4894dc886b62..3629b15ecc17 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -969,6 +969,33 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) rport->dev_loss_tmo = ha->port_down_retry_count + 5; } +static void +qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) +{ + struct Scsi_Host *host = rport_to_shost(rport); + fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + + qla2x00_abort_fcport_cmds(fcport); + + /* + * Transport has effectively 'deleted' the rport, clear + * all local references. + */ + spin_lock_irq(host->host_lock); + fcport->rport = NULL; + *((fc_port_t **)rport->dd_data) = NULL; + spin_unlock_irq(host->host_lock); +} + +static void +qla2x00_terminate_rport_io(struct fc_rport *rport) +{ + fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + + qla2x00_abort_fcport_cmds(fcport); + scsi_target_unblock(&rport->dev); +} + static int qla2x00_issue_lip(struct Scsi_Host *shost) { @@ -1227,6 +1254,8 @@ struct fc_function_template qla2xxx_transport_functions = { .show_rport_dev_loss_tmo = 1, .issue_fc_host_lip = qla2x00_issue_lip, + .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, + .terminate_rport_io = qla2x00_terminate_rport_io, .get_fc_host_stats = qla2x00_get_fc_host_stats, .vport_create = qla24xx_vport_create, @@ -1270,6 +1299,8 @@ struct fc_function_template qla2xxx_transport_vport_functions = { .show_rport_dev_loss_tmo = 1, .issue_fc_host_lip = qla2x00_issue_lip, + .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, + .terminate_rport_io = qla2x00_terminate_rport_io, .get_fc_host_stats = qla2x00_get_fc_host_stats, }; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 3750319f4968..ab5928bee6c9 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1548,7 +1548,6 @@ typedef struct fc_port { int login_retry; atomic_t port_down_timer; - spinlock_t rport_lock; struct fc_rport *rport, *drport; u32 supported_classes; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 193f688ec3d7..d6eccbe5c6fc 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -68,6 +68,8 @@ extern int num_hosts; extern int qla2x00_loop_reset(scsi_qla_host_t *); extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int); +extern void qla2x00_abort_fcport_cmds(fc_port_t *); + /* * Global Functions in qla_mid.c source file. */ diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 364be7d06875..6ffaf0ee0dd3 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1827,12 +1827,11 @@ qla2x00_rport_del(void *data) { fc_port_t *fcport = data; struct fc_rport *rport; - unsigned long flags; - spin_lock_irqsave(&fcport->rport_lock, flags); + spin_lock_irq(fcport->ha->host->host_lock); rport = fcport->drport; fcport->drport = NULL; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + spin_unlock_irq(fcport->ha->host->host_lock); if (rport) fc_remote_port_delete(rport); } @@ -1861,7 +1860,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) atomic_set(&fcport->state, FCS_UNCONFIGURED); fcport->flags = FCF_RLC_SUPPORT; fcport->supported_classes = FC_COS_UNSPECIFIED; - spin_lock_init(&fcport->rport_lock); return fcport; } @@ -2220,28 +2218,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) { struct fc_rport_identifiers rport_ids; struct fc_rport *rport; - unsigned long flags; if (fcport->drport) qla2x00_rport_del(fcport); - if (fcport->rport) - return; rport_ids.node_name = wwn_to_u64(fcport->node_name); rport_ids.port_name = wwn_to_u64(fcport->port_name); rport_ids.port_id = fcport->d_id.b.domain << 16 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; - rport = fc_remote_port_add(ha->host, 0, &rport_ids); + fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); if (!rport) { qla_printk(KERN_WARNING, ha, "Unable to allocate fc remote port!\n"); return; } - spin_lock_irqsave(&fcport->rport_lock, flags); - fcport->rport = rport; + spin_lock_irq(fcport->ha->host->host_lock); *((fc_port_t **)rport->dd_data) = fcport; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + spin_unlock_irq(fcport->ha->host->host_lock); rport->supported_classes = fcport->supported_classes; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 0e8e0920bedc..6254d82b1c0c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -386,7 +386,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) } /* Close window on fcport/rport state-transitioning. */ - if (!*(fc_port_t **)rport->dd_data) { + if (fcport->drport) { cmd->result = DID_IMM_RETRY << 16; goto qc_fail_command; } @@ -453,7 +453,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) } /* Close window on fcport/rport state-transitioning. */ - if (!*(fc_port_t **)rport->dd_data) { + if (fcport->drport) { cmd->result = DID_IMM_RETRY << 16; goto qc24_fail_command; } @@ -617,6 +617,40 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) return (return_status); } +void +qla2x00_abort_fcport_cmds(fc_port_t *fcport) +{ + int cnt; + unsigned long flags; + srb_t *sp; + scsi_qla_host_t *ha = fcport->ha; + scsi_qla_host_t *pha = to_qla_parent(ha); + + spin_lock_irqsave(&pha->hardware_lock, flags); + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { + sp = pha->outstanding_cmds[cnt]; + if (!sp) + continue; + if (sp->fcport != fcport) + continue; + + spin_unlock_irqrestore(&pha->hardware_lock, flags); + if (ha->isp_ops->abort_command(ha, sp)) { + DEBUG2(qla_printk(KERN_WARNING, ha, + "Abort failed -- %lx\n", sp->cmd->serial_number)); + } else { + if (qla2x00_eh_wait_on_command(ha, sp->cmd) != + QLA_SUCCESS) + DEBUG2(qla_printk(KERN_WARNING, ha, + "Abort failed while waiting -- %lx\n", + sp->cmd->serial_number)); + + } + spin_lock_irqsave(&pha->hardware_lock, flags); + } + spin_unlock_irqrestore(&pha->hardware_lock, flags); +} + static void qla2x00_block_error_handler(struct scsi_cmnd *cmnd) { @@ -1883,7 +1917,6 @@ 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) @@ -1891,19 +1924,13 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, rport = fcport->rport; if (defer) { - spin_lock_irqsave(&fcport->rport_lock, flags); + spin_lock_irq(ha->host->host_lock); fcport->drport = rport; - fcport->rport = NULL; - *(fc_port_t **)rport->dd_data = NULL; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + spin_unlock_irq(ha->host->host_lock); set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); - } else { - spin_lock_irqsave(&fcport->rport_lock, flags); - fcport->rport = NULL; - *(fc_port_t **)rport->dd_data = NULL; - spin_unlock_irqrestore(&fcport->rport_lock, flags); + qla2xxx_wake_dpc(ha); + } else fc_remote_port_delete(rport); - } } /* -- cgit v1.2.3