[patch 54/60] qla2xxx: Add dev_loss_tmo_callbk/terminate_rport_iocallback support.

From: Greg KH
Date: Mon Aug 18 2008 - 15:11:49 EST


2.6.26-stable review patch. If anyone has any objections, please let us know.

------------------
From: Seokmann Ju <seokmann.ju@xxxxxxxxxx>

[ Upstream commit 5f3a9a207f1fccde476dd31b4c63ead2967d934f ]

Signed-off-by: Seokmann Ju <seokmann.ju@xxxxxxxxxx>
Signed-off-by: Andrew Vasquez <andrew.vasquez@xxxxxxxxxx>
Signed-off-by: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
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(-)

--- 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_rpo
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)
{
@@ -1253,6 +1280,8 @@ struct fc_function_template qla2xxx_tran
.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,
@@ -1296,6 +1325,8 @@ struct fc_function_template qla2xxx_tran
.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,
};

--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1544,7 +1544,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;

--- 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
extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t,
uint16_t, uint16_t);

+extern void qla2x00_abort_fcport_cmds(fc_port_t *);
+
/*
* Global Functions in qla_mid.c source file.
*/
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1864,12 +1864,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);
}
@@ -1898,7 +1897,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha
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;
}
@@ -2243,28 +2241,24 @@ qla2x00_reg_remote_port(scsi_qla_host_t
{
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;

--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -388,7 +388,7 @@ qla2x00_queuecommand(struct scsi_cmnd *c
}

/* 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;
}
@@ -455,7 +455,7 @@ qla24xx_queuecommand(struct scsi_cmnd *c
}

/* 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_hos
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)
{
@@ -1813,7 +1847,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)
@@ -1821,19 +1854,13 @@ qla2x00_schedule_rport_del(struct scsi_q

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);
- }
}

/*

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/