Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f3a9a20 authored by Seokmann Ju's avatar Seokmann Ju Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Add dev_loss_tmo_callbk/terminate_rport_io callback support.

parent bbfb21da
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -994,6 +994,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)
{
@@ -1253,6 +1280,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,
@@ -1296,6 +1325,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,
};

+0 −1
Original line number Diff line number Diff line
@@ -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;

+2 −0
Original line number Diff line number Diff line
@@ -71,6 +71,8 @@ extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
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.
 */
+5 −11
Original line number Diff line number Diff line
@@ -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, 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;
}
@@ -2243,28 +2241,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;

+40 −13
Original line number Diff line number Diff line
@@ -388,7 +388,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;
	}
@@ -455,7 +455,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)
{
@@ -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,20 +1854,14 @@ 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);
}
}

/*
 * qla2x00_mark_device_lost Updates fcport state when device goes offline.