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

Commit 9ba56b95 authored by Giridhar Malavali's avatar Giridhar Malavali Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Consolidation of SRB processing.



Rework the structures related to SRB processing to minimize the memory
allocations per I/O and manage resources associated with and completions
from common routines.

Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 69e5f1ea
Loading
Loading
Loading
Loading
+44 −42
Original line number Diff line number Diff line
@@ -11,29 +11,36 @@
#include <linux/delay.h>

/* BSG support for ELS/CT pass through */
inline srb_t *
qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
void
qla2x00_bsg_job_done(void *data, void *ptr, int res)
{
	srb_t *sp;
	struct qla_hw_data *ha = vha->hw;
	struct srb_ctx *ctx;
	srb_t *sp = (srb_t *)ptr;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
	struct fc_bsg_job *bsg_job = sp->u.bsg_job;

	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
	if (!sp)
		goto done;
	ctx = kzalloc(size, GFP_KERNEL);
	if (!ctx) {
		mempool_free(sp, ha->srb_mempool);
		sp = NULL;
		goto done;
	bsg_job->reply->result = res;
	bsg_job->job_done(bsg_job);
	sp->free(vha, sp);
}

	memset(sp, 0, sizeof(*sp));
	sp->fcport = fcport;
	sp->ctx = ctx;
	ctx->iocbs = 1;
done:
	return sp;
void
qla2x00_bsg_sp_free(void *data, void *ptr)
{
	srb_t *sp = (srb_t *)ptr;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
	struct fc_bsg_job *bsg_job = sp->u.bsg_job;
	struct qla_hw_data *ha = vha->hw;

	dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
	    bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);

	dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
	    bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);

	if (sp->type == SRB_CT_CMD ||
	    sp->type == SRB_ELS_CMD_HST)
		kfree(sp->fcport);
	mempool_free(sp, vha->hw->srb_mempool);
}

int
@@ -217,6 +224,7 @@ qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
	bsg_job->job_done(bsg_job);
	return ret;
}

static int
qla2x00_process_els(struct fc_bsg_job *bsg_job)
{
@@ -230,7 +238,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
	int req_sg_cnt, rsp_sg_cnt;
	int rval =  (DRIVER_ERROR << 16);
	uint16_t nextlid = 0;
	struct srb_ctx *els;

	if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
		rport = bsg_job->rport;
@@ -337,20 +344,21 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
	}

	/* Alloc SRB structure */
	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp) {
		rval = -ENOMEM;
		goto done_unmap_sg;
	}

	els = sp->ctx;
	els->type =
	sp->type =
		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
		SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
	els->name =
	sp->name =
		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
		"bsg_els_rpt" : "bsg_els_hst");
	els->u.bsg_job = bsg_job;
	sp->u.bsg_job = bsg_job;
	sp->free = qla2x00_bsg_sp_free;
	sp->done = qla2x00_bsg_job_done;

	ql_dbg(ql_dbg_user, vha, 0x700a,
	    "bsg rqst type: %s els type: %x - loop-id=%x "
@@ -362,7 +370,6 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
	if (rval != QLA_SUCCESS) {
		ql_log(ql_log_warn, vha, 0x700e,
		    "qla2x00_start_sp failed = %d\n", rval);
		kfree(sp->ctx);
		mempool_free(sp, ha->srb_mempool);
		rval = -EIO;
		goto done_unmap_sg;
@@ -409,7 +416,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
	uint16_t loop_id;
	struct fc_port *fcport;
	char  *type = "FC_BSG_HST_CT";
	struct srb_ctx *ct;

	req_sg_cnt =
		dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
@@ -486,19 +492,20 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
	fcport->loop_id = loop_id;

	/* Alloc SRB structure */
	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp) {
		ql_log(ql_log_warn, vha, 0x7015,
		    "qla2x00_get_ctx_bsg_sp failed.\n");
		    "qla2x00_get_sp failed.\n");
		rval = -ENOMEM;
		goto done_free_fcport;
	}

	ct = sp->ctx;
	ct->type = SRB_CT_CMD;
	ct->name = "bsg_ct";
	ct->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
	ct->u.bsg_job = bsg_job;
	sp->type = SRB_CT_CMD;
	sp->name = "bsg_ct";
	sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
	sp->u.bsg_job = bsg_job;
	sp->free = qla2x00_bsg_sp_free;
	sp->done = qla2x00_bsg_job_done;

	ql_dbg(ql_dbg_user, vha, 0x7016,
	    "bsg rqst type: %s else type: %x - "
@@ -511,7 +518,6 @@ qla2x00_process_ct(struct fc_bsg_job *bsg_job)
	if (rval != QLA_SUCCESS) {
		ql_log(ql_log_warn, vha, 0x7017,
		    "qla2x00_start_sp failed=%d.\n", rval);
		kfree(sp->ctx);
		mempool_free(sp, ha->srb_mempool);
		rval = -EIO;
		goto done_free_fcport;
@@ -1669,7 +1675,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
	int cnt, que;
	unsigned long flags;
	struct req_que *req;
	struct srb_ctx *sp_bsg;

	/* find the bsg job from the active list of commands */
	spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1681,11 +1686,9 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
		for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
			sp = req->outstanding_cmds[cnt];
			if (sp) {
				sp_bsg = sp->ctx;

				if (((sp_bsg->type == SRB_CT_CMD) ||
					(sp_bsg->type == SRB_ELS_CMD_HST))
					&& (sp_bsg->u.bsg_job == bsg_job)) {
				if (((sp->type == SRB_CT_CMD) ||
					(sp->type == SRB_ELS_CMD_HST))
					&& (sp->u.bsg_job == bsg_job)) {
					spin_unlock_irqrestore(&ha->hardware_lock, flags);
					if (ha->isp_ops->abort_command(sp)) {
						ql_log(ql_log_warn, vha, 0x7089,
@@ -1715,7 +1718,6 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
	if (bsg_job->request->msgcode == FC_BSG_HST_CT)
		kfree(sp->fcport);
	kfree(sp->ctx);
	mempool_free(sp, ha->srb_mempool);
	return 0;
}
+3 −2
Original line number Diff line number Diff line
@@ -14,10 +14,11 @@
 * | Module Init and Probe        |       0x011f       | 0x4b,0xfa      |
 * | Mailbox commands             |       0x1139       | 0x112c-0x112e  |
 * | Device Discovery             |       0x2084       |                |
 * | Queue Command and IO tracing |       0x302f       | 0x3008         |
 * | Queue Command and IO tracing |       0x302f       | 0x3006,0x3008  |
 * |                              |                    | 0x302d-0x302e  |
 * | DPC Thread                   |       0x401c       |		|
 * | Async Events                 |       0x5057       | 0x5052		|
 * | Async Events                 |       0x5057       | 0x502b-0x502f  |
 * |                              |                    | 0x5047,0x5052  |
 * | Timer Routines               |       0x6011       | 0x600e-0x600f  |
 * | User Space Interactions      |       0x709e       | 0x7018,0x702e  |
 * |                              |                    | 0x7039,0x7045  |
+27 −17
Original line number Diff line number Diff line
@@ -202,20 +202,12 @@ struct sd_dif_tuple {
/*
 * SCSI Request Block
 */
typedef struct srb {
	atomic_t ref_count;
	struct fc_port *fcport;
	uint32_t handle;

struct srb_cmd {
	struct scsi_cmnd *cmd;		/* Linux SCSI command pkt */

	uint16_t flags;

	uint32_t request_sense_length;
	uint8_t *request_sense_ptr;

	void *ctx;
} srb_t;
};

/*
 * SRB flag definitions
@@ -254,10 +246,7 @@ struct srb_iocb {
	} u;

	struct timer_list timer;

	void (*done)(srb_t *);
	void (*free)(srb_t *);
	void (*timeout)(srb_t *);
	void (*timeout)(void *);
};

/* Values for srb_ctx type */
@@ -268,16 +257,37 @@ struct srb_iocb {
#define SRB_CT_CMD	5
#define SRB_ADISC_CMD	6
#define SRB_TM_CMD	7
#define SRB_SCSI_CMD	8

struct srb_ctx {
typedef struct srb {
	atomic_t ref_count;
	struct fc_port *fcport;
	uint32_t handle;
	uint16_t flags;
	uint16_t type;
	char *name;
	int iocbs;
	union {
		struct srb_iocb *iocb_cmd;
		struct srb_iocb iocb_cmd;
		struct fc_bsg_job *bsg_job;
		struct srb_cmd scmd;
	} u;
};
	void (*done)(void *, void *, int);
	void (*free)(void *, void *);
} srb_t;

#define GET_CMD_SP(sp) (sp->u.scmd.cmd)
#define SET_CMD_SP(sp, cmd) (sp->u.scmd.cmd = cmd)
#define GET_CMD_CTX_SP(sp) (sp->u.scmd.ctx)

#define GET_CMD_SENSE_LEN(sp) \
	(sp->u.scmd.request_sense_length)
#define SET_CMD_SENSE_LEN(sp, len) \
	(sp->u.scmd.request_sense_length = len)
#define GET_CMD_SENSE_PTR(sp) \
	(sp->u.scmd.request_sense_ptr)
#define SET_CMD_SENSE_PTR(sp, ptr) \
	(sp->u.scmd.request_sense_ptr = ptr)

struct msg_echo_lb {
	dma_addr_t send_dma;
+5 −4
Original line number Diff line number Diff line
@@ -71,8 +71,6 @@ extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern void qla2x00_async_tm_cmd_done(struct scsi_qla_host *, fc_port_t *,
	struct srb_iocb *);
extern void *qla2x00_alloc_iocbs(struct scsi_qla_host *, srb_t *);
extern int qla24xx_update_fcport_fcp_prio(scsi_qla_host_t *, fc_port_t *);

@@ -156,8 +154,7 @@ extern void qla2x00_do_dpc_all_vps(scsi_qla_host_t *);
extern int qla24xx_vport_create_req_sanity_check(struct fc_vport *);
extern scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *);

extern void qla2x00_sp_compl(struct qla_hw_data *, srb_t *);

extern void qla2x00_sp_free_dma(void *, void *);
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);

extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
@@ -542,6 +539,10 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *);

/* IOCB related functions */
extern int qla82xx_start_scsi(srb_t *);
extern void qla2x00_sp_free(void *, void *);
extern void qla2x00_sp_timeout(unsigned long);
extern void qla2x00_bsg_job_done(void *, void *, int);
extern void qla2x00_bsg_sp_free(void *, void *);

/* Interrupt related */
extern irqreturn_t qla82xx_intr_handler(int, void *);
+98 −158
Original line number Diff line number Diff line
@@ -41,11 +41,10 @@ static int qla25xx_init_queues(struct qla_hw_data *);

/* SRB Extensions ---------------------------------------------------------- */

static void
qla2x00_ctx_sp_timeout(unsigned long __data)
void
qla2x00_sp_timeout(unsigned long __data)
{
	srb_t *sp = (srb_t *)__data;
	struct srb_ctx *ctx;
	struct srb_iocb *iocb;
	fc_port_t *fcport = sp->fcport;
	struct qla_hw_data *ha = fcport->vha->hw;
@@ -55,77 +54,23 @@ qla2x00_ctx_sp_timeout(unsigned long __data)
	spin_lock_irqsave(&ha->hardware_lock, flags);
	req = ha->req_q_map[0];
	req->outstanding_cmds[sp->handle] = NULL;
	ctx = sp->ctx;
	iocb = ctx->u.iocb_cmd;
	iocb = &sp->u.iocb_cmd;
	iocb->timeout(sp);
	iocb->free(sp);
	sp->free(fcport->vha, sp);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}

static void
qla2x00_ctx_sp_free(srb_t *sp)
void
qla2x00_sp_free(void *data, void *ptr)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *iocb = ctx->u.iocb_cmd;
	struct scsi_qla_host *vha = sp->fcport->vha;
	srb_t *sp = (srb_t *)ptr;
	struct srb_iocb *iocb = &sp->u.iocb_cmd;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;

	del_timer(&iocb->timer);
	kfree(iocb);
	kfree(ctx);
	mempool_free(sp, sp->fcport->vha->hw->srb_mempool);

	QLA_VHA_MARK_NOT_BUSY(vha);
}

inline srb_t *
qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
    unsigned long tmo)
{
	srb_t *sp = NULL;
	struct qla_hw_data *ha = vha->hw;
	struct srb_ctx *ctx;
	struct srb_iocb *iocb;
	uint8_t bail;

	QLA_VHA_MARK_BUSY(vha, bail);
	if (bail)
		return NULL;

	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
	if (!sp)
		goto done;
	ctx = kzalloc(size, GFP_KERNEL);
	if (!ctx) {
		mempool_free(sp, ha->srb_mempool);
		sp = NULL;
		goto done;
	}
	iocb = kzalloc(sizeof(struct srb_iocb), GFP_KERNEL);
	if (!iocb) {
		mempool_free(sp, ha->srb_mempool);
		sp = NULL;
		kfree(ctx);
		goto done;
	}
	mempool_free(sp, vha->hw->srb_mempool);

	memset(sp, 0, sizeof(*sp));
	sp->fcport = fcport;
	sp->ctx = ctx;
	ctx->iocbs = 1;
	ctx->u.iocb_cmd = iocb;
	iocb->free = qla2x00_ctx_sp_free;

	init_timer(&iocb->timer);
	if (!tmo)
		goto done;
	iocb->timer.expires = jiffies + tmo * HZ;
	iocb->timer.data = (unsigned long)sp;
	iocb->timer.function = qla2x00_ctx_sp_timeout;
	add_timer(&iocb->timer);
done:
	if (!sp)
	QLA_VHA_MARK_NOT_BUSY(vha);
	return sp;
}

/* Asynchronous Login/Logout Routines -------------------------------------- */
@@ -149,19 +94,19 @@ qla2x00_get_async_timeout(struct scsi_qla_host *vha)
}

static void
qla2x00_async_iocb_timeout(srb_t *sp)
qla2x00_async_iocb_timeout(void *data)
{
	srb_t *sp = (srb_t *)data;
	fc_port_t *fcport = sp->fcport;
	struct srb_ctx *ctx = sp->ctx;

	ql_dbg(ql_dbg_disc, fcport->vha, 0x2071,
	    "Async-%s timeout - hdl=%x portid=%02x%02x%02x.\n",
	    ctx->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
	    sp->name, sp->handle, fcport->d_id.b.domain, fcport->d_id.b.area,
	    fcport->d_id.b.al_pa);

	fcport->flags &= ~FCF_ASYNC_SENT;
	if (ctx->type == SRB_LOGIN_CMD) {
		struct srb_iocb *lio = ctx->u.iocb_cmd;
	if (sp->type == SRB_LOGIN_CMD) {
		struct srb_iocb *lio = &sp->u.iocb_cmd;
		qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
		/* Retry as needed. */
		lio->u.logio.data[0] = MBS_COMMAND_ERROR;
@@ -173,14 +118,16 @@ qla2x00_async_iocb_timeout(srb_t *sp)
}

static void
qla2x00_async_login_ctx_done(srb_t *sp)
qla2x00_async_login_sp_done(void *data, void *ptr, int res)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;
	srb_t *sp = (srb_t *)ptr;
	struct srb_iocb *lio = &sp->u.iocb_cmd;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;

	if (!test_bit(UNLOADING, &vha->dpc_flags))
		qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
		    lio->u.logio.data);
	lio->free(sp);
	sp->free(sp->fcport->vha, sp);
}

int
@@ -188,22 +135,21 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
    uint16_t *data)
{
	srb_t *sp;
	struct srb_ctx *ctx;
	struct srb_iocb *lio;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    qla2x00_get_async_timeout(vha) + 2);
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	ctx = sp->ctx;
	ctx->type = SRB_LOGIN_CMD;
	ctx->name = "login";
	lio = ctx->u.iocb_cmd;
	sp->type = SRB_LOGIN_CMD;
	sp->name = "login";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	lio = &sp->u.iocb_cmd;
	lio->timeout = qla2x00_async_iocb_timeout;
	lio->done = qla2x00_async_login_ctx_done;
	sp->done = qla2x00_async_login_sp_done;
	lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
@@ -219,42 +165,43 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
	return rval;

done_free_sp:
	lio->free(sp);
	sp->free(fcport->vha, sp);
done:
	return rval;
}

static void
qla2x00_async_logout_ctx_done(srb_t *sp)
qla2x00_async_logout_sp_done(void *data, void *ptr, int res)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;
	srb_t *sp = (srb_t *)ptr;
	struct srb_iocb *lio = &sp->u.iocb_cmd;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;

	if (!test_bit(UNLOADING, &vha->dpc_flags))
		qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
		    lio->u.logio.data);
	lio->free(sp);
	sp->free(sp->fcport->vha, sp);
}

int
qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
{
	srb_t *sp;
	struct srb_ctx *ctx;
	struct srb_iocb *lio;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    qla2x00_get_async_timeout(vha) + 2);
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	ctx = sp->ctx;
	ctx->type = SRB_LOGOUT_CMD;
	ctx->name = "logout";
	lio = ctx->u.iocb_cmd;
	sp->type = SRB_LOGOUT_CMD;
	sp->name = "logout";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	lio = &sp->u.iocb_cmd;
	lio->timeout = qla2x00_async_iocb_timeout;
	lio->done = qla2x00_async_logout_ctx_done;
	sp->done = qla2x00_async_logout_sp_done;
	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
		goto done_free_sp;
@@ -266,20 +213,22 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
	return rval;

done_free_sp:
	lio->free(sp);
	sp->free(fcport->vha, sp);
done:
	return rval;
}

static void
qla2x00_async_adisc_ctx_done(srb_t *sp)
qla2x00_async_adisc_sp_done(void *data, void *ptr, int res)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;
	srb_t *sp = (srb_t *)ptr;
	struct srb_iocb *lio = &sp->u.iocb_cmd;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;

	if (!test_bit(UNLOADING, &vha->dpc_flags))
		qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
		    lio->u.logio.data);
	lio->free(sp);
	sp->free(sp->fcport->vha, sp);
}

int
@@ -287,22 +236,21 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
    uint16_t *data)
{
	srb_t *sp;
	struct srb_ctx *ctx;
	struct srb_iocb *lio;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    qla2x00_get_async_timeout(vha) + 2);
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	ctx = sp->ctx;
	ctx->type = SRB_ADISC_CMD;
	ctx->name = "adisc";
	lio = ctx->u.iocb_cmd;
	sp->type = SRB_ADISC_CMD;
	sp->name = "adisc";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	lio = &sp->u.iocb_cmd;
	lio->timeout = qla2x00_async_iocb_timeout;
	lio->done = qla2x00_async_adisc_ctx_done;
	sp->done = qla2x00_async_adisc_sp_done;
	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
	rval = qla2x00_start_sp(sp);
@@ -316,46 +264,62 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
	return rval;

done_free_sp:
	lio->free(sp);
	sp->free(fcport->vha, sp);
done:
	return rval;
}

static void
qla2x00_async_tm_cmd_ctx_done(srb_t *sp)
qla2x00_async_tm_cmd_done(void *data, void *ptr, int res)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *iocb = (struct srb_iocb *)ctx->u.iocb_cmd;
	srb_t *sp = (srb_t *)ptr;
	struct srb_iocb *iocb = &sp->u.iocb_cmd;
	struct scsi_qla_host *vha = (scsi_qla_host_t *)data;
	uint32_t flags;
	uint16_t lun;
	int rval;

	if (!test_bit(UNLOADING, &vha->dpc_flags)) {
		flags = iocb->u.tmf.flags;
		lun = (uint16_t)iocb->u.tmf.lun;

		/* Issue Marker IOCB */
		rval = qla2x00_marker(vha, vha->hw->req_q_map[0],
			vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
			flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);

	qla2x00_async_tm_cmd_done(sp->fcport->vha, sp->fcport, iocb);
	iocb->free(sp);
		if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
			ql_dbg(ql_dbg_taskm, vha, 0x8030,
			    "TM IOCB failed (%x).\n", rval);
		}
	}
	sp->free(sp->fcport->vha, sp);
}

int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t tm_flags, uint32_t lun,
	uint32_t tag)
{
	struct scsi_qla_host *vha = fcport->vha;
	srb_t *sp;
	struct srb_ctx *ctx;
	struct srb_iocb *tcf;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    qla2x00_get_async_timeout(vha) + 2);
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	ctx = sp->ctx;
	ctx->type = SRB_TM_CMD;
	ctx->name = "tmf";
	tcf = ctx->u.iocb_cmd;
	tcf->u.tmf.flags = flags;
	sp->type = SRB_TM_CMD;
	sp->name = "tmf";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	tcf = &sp->u.iocb_cmd;
	tcf->u.tmf.flags = tm_flags;
	tcf->u.tmf.lun = lun;
	tcf->u.tmf.data = tag;
	tcf->timeout = qla2x00_async_iocb_timeout;
	tcf->done = qla2x00_async_tm_cmd_ctx_done;
	sp->done = qla2x00_async_tm_cmd_done;

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
@@ -368,7 +332,7 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
	return rval;

done_free_sp:
	tcf->free(sp);
	sp->free(fcport->vha, sp);
done:
	return rval;
}
@@ -452,30 +416,6 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
	return;
}

void
qla2x00_async_tm_cmd_done(struct scsi_qla_host *vha, fc_port_t *fcport,
    struct srb_iocb *iocb)
{
	int rval;
	uint32_t flags;
	uint16_t lun;

	flags = iocb->u.tmf.flags;
	lun = (uint16_t)iocb->u.tmf.lun;

	/* Issue Marker IOCB */
	rval = qla2x00_marker(vha, vha->hw->req_q_map[0],
		vha->hw->rsp_q_map[0], fcport->loop_id, lun,
		flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);

	if ((rval != QLA_SUCCESS) || iocb->u.tmf.data) {
		ql_dbg(ql_dbg_taskm, vha, 0x8030,
		    "TM IOCB failed (%x).\n", rval);
	}

	return;
}

/****************************************************************************/
/*                QLogic ISP2x00 Hardware Support Functions.                */
/****************************************************************************/
Loading