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

Commit 4916392b authored by Madhuranath Iyengar's avatar Madhuranath Iyengar Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Provide common framework for BSG and IOCB commands.



Currently, BSG and IOCB/Logio commands have a different
framework (srb structs). The purpose of this effort is to
consolidate them into a generalized framework for these
as well as other asynchronous operations in the future.

Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent b7d2280c
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
{
	srb_t *sp;
	struct qla_hw_data *ha = vha->hw;
	struct srb_bsg_ctx *ctx;
	struct srb_ctx *ctx;

	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
	if (!sp)
@@ -208,7 +208,7 @@ 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_bsg *els;
	struct srb_ctx *els;

	/*  Multiple SG's are not supported for ELS requests */
	if (bsg_job->request_payload.sg_cnt > 1 ||
@@ -307,17 +307,17 @@ qla2x00_process_els(struct fc_bsg_job *bsg_job)
	}

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

	els = sp->ctx;
	els->ctx.type =
	els->type =
		(bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
		SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
	els->bsg_job = bsg_job;
	els->u.bsg_job = bsg_job;

	DEBUG2(qla_printk(KERN_INFO, ha,
		"scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
@@ -361,7 +361,7 @@ 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_bsg *ct;
	struct srb_ctx *ct;

	/* pass through is supported only for ISP 4Gb or higher */
	if (!IS_FWI2_CAPABLE(ha)) {
@@ -442,15 +442,15 @@ 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_bsg));
	sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
	if (!sp) {
		rval = -ENOMEM;
		goto done_free_fcport;
	}

	ct = sp->ctx;
	ct->ctx.type = SRB_CT_CMD;
	ct->bsg_job = bsg_job;
	ct->type = SRB_CT_CMD;
	ct->u.bsg_job = bsg_job;

	DEBUG2(qla_printk(KERN_INFO, ha,
		"scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
@@ -1155,7 +1155,7 @@ qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
	int cnt, que;
	unsigned long flags;
	struct req_que *req;
	struct srb_bsg *sp_bsg;
	struct srb_ctx *sp_bsg;

	/* find the bsg job from the active list of commands */
	spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -1167,11 +1167,11 @@ 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 = (struct srb_bsg *)sp->ctx;
				sp_bsg = sp->ctx;

				if (((sp_bsg->ctx.type == SRB_CT_CMD) ||
					(sp_bsg->ctx.type == SRB_ELS_CMD_HST))
					&& (sp_bsg->bsg_job == bsg_job)) {
				if (((sp_bsg->type == SRB_CT_CMD) ||
					(sp_bsg->type == SRB_ELS_CMD_HST))
					&& (sp_bsg->u.bsg_job == bsg_job)) {
					if (ha->isp_ops->abort_command(sp)) {
						DEBUG2(qla_printk(KERN_INFO, ha,
						    "scsi(%ld): mbx "
+23 −25
Original line number Diff line number Diff line
@@ -214,16 +214,16 @@ typedef struct srb {
/*
 * SRB extensions.
 */
#define SRB_LOGIN_CMD	1
#define SRB_LOGOUT_CMD	2
#define SRB_ELS_CMD_RPT 3
#define SRB_ELS_CMD_HST 4
#define SRB_CT_CMD 5
#define SRB_ADISC_CMD	6

struct srb_ctx {
	uint16_t type;
	char *name;
struct srb_iocb {
	union {
		struct {
			uint16_t flags;
#define SRB_LOGIN_RETRIED	BIT_0
#define SRB_LOGIN_COND_PLOGI	BIT_1
#define SRB_LOGIN_SKIP_PRLI	BIT_2
			uint16_t data[2];
		} logio;
	} u;

	struct timer_list timer;

@@ -232,23 +232,21 @@ struct srb_ctx {
	void (*timeout)(srb_t *);
};

struct srb_logio {
	struct srb_ctx ctx;

#define SRB_LOGIN_RETRIED	BIT_0
#define SRB_LOGIN_COND_PLOGI	BIT_1
#define SRB_LOGIN_SKIP_PRLI	BIT_2
	uint16_t flags;
	uint16_t data[2];
};
/* Values for srb_ctx type */
#define SRB_LOGIN_CMD	1
#define SRB_LOGOUT_CMD	2
#define SRB_ELS_CMD_RPT 3
#define SRB_ELS_CMD_HST 4
#define SRB_CT_CMD	5
#define SRB_ADISC_CMD	6

struct srb_bsg_ctx {
struct srb_ctx {
	uint16_t type;
};

struct srb_bsg {
	struct srb_bsg_ctx ctx;
	char *name;
	union {
		struct srb_iocb *iocb_cmd;
		struct fc_bsg_job *bsg_job;
	} u;
};

struct msg_echo_lb {
+3 −3
Original line number Diff line number Diff line
@@ -58,11 +58,11 @@ extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_adisc(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
extern void qla2x00_async_login_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
extern void qla2x00_async_logout_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
extern void qla2x00_async_adisc_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);

extern fc_port_t *
+78 −57
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ qla2x00_ctx_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;
	struct req_que *req;
@@ -57,17 +58,21 @@ qla2x00_ctx_sp_timeout(unsigned long __data)
	req = ha->req_q_map[0];
	req->outstanding_cmds[sp->handle] = NULL;
	ctx = sp->ctx;
	ctx->timeout(sp);
	iocb = ctx->u.iocb_cmd;
	iocb->timeout(sp);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);

	ctx->free(sp);
	iocb->free(sp);
}

void
qla2x00_ctx_sp_free(srb_t *sp)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *iocb = ctx->u.iocb_cmd;

	del_timer_sync(&iocb->timer);
	kfree(iocb);
	kfree(ctx);
	mempool_free(sp, sp->fcport->vha->hw->srb_mempool);
}
@@ -79,6 +84,7 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
	srb_t *sp;
	struct qla_hw_data *ha = vha->hw;
	struct srb_ctx *ctx;
	struct srb_iocb *iocb;

	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
	if (!sp)
@@ -86,21 +92,30 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
	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;
	}

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

	init_timer(&ctx->timer);
	init_timer(&iocb->timer);
	if (!tmo)
		goto done;
	ctx->timer.expires = jiffies + tmo * HZ;
	ctx->timer.data = (unsigned long)sp;
	ctx->timer.function = qla2x00_ctx_sp_timeout;
	add_timer(&ctx->timer);
	iocb->timer.expires = jiffies + tmo * HZ;
	iocb->timer.data = (unsigned long)sp;
	iocb->timer.function = qla2x00_ctx_sp_timeout;
	add_timer(&iocb->timer);
done:
	return sp;
}
@@ -113,25 +128,26 @@ static void
qla2x00_async_logio_timeout(srb_t *sp)
{
	fc_port_t *fcport = sp->fcport;
	struct srb_logio *lio = sp->ctx;
	struct srb_ctx *ctx = sp->ctx;

	DEBUG2(printk(KERN_WARNING
	    "scsi(%ld:%x): Async-%s timeout.\n",
	    fcport->vha->host_no, sp->handle, lio->ctx.name));
	    fcport->vha->host_no, sp->handle, ctx->name));

	fcport->flags &= ~FCF_ASYNC_SENT;
	if (lio->ctx.type == SRB_LOGIN_CMD)
	if (ctx->type == SRB_LOGIN_CMD)
		qla2x00_post_async_logout_work(fcport->vha, fcport, NULL);
}

static void
qla2x00_async_login_ctx_done(srb_t *sp)
{
	struct srb_logio *lio = sp->ctx;
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;

	qla2x00_post_async_login_done_work(sp->fcport->vha, sp->fcport,
	    lio->data);
	lio->ctx.free(sp);
		lio->u.logio.data);
	lio->free(sp);
}

int
@@ -140,23 +156,25 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
{
	struct qla_hw_data *ha = vha->hw;
	srb_t *sp;
	struct srb_logio *lio;
	struct srb_ctx *ctx;
	struct srb_iocb *lio;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    ELS_TMO_2_RATOV(ha) + 2);
	if (!sp)
		goto done;

	lio = sp->ctx;
	lio->ctx.type = SRB_LOGIN_CMD;
	lio->ctx.name = "login";
	lio->ctx.timeout = qla2x00_async_logio_timeout;
	lio->ctx.done = qla2x00_async_login_ctx_done;
	lio->flags |= SRB_LOGIN_COND_PLOGI;
	ctx = sp->ctx;
	ctx->type = SRB_LOGIN_CMD;
	ctx->name = "login";
	lio = ctx->u.iocb_cmd;
	lio->timeout = qla2x00_async_logio_timeout;
	lio->done = qla2x00_async_login_ctx_done;
	lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
		lio->flags |= SRB_LOGIN_RETRIED;
		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
		goto done_free_sp;
@@ -169,8 +187,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
	return rval;

done_free_sp:
	del_timer_sync(&lio->ctx.timer);
	lio->ctx.free(sp);
	lio->free(sp);
done:
	return rval;
}
@@ -178,11 +195,12 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
static void
qla2x00_async_logout_ctx_done(srb_t *sp)
{
	struct srb_logio *lio = sp->ctx;
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;

	qla2x00_post_async_logout_done_work(sp->fcport->vha, sp->fcport,
	    lio->data);
	lio->ctx.free(sp);
	    lio->u.logio.data);
	lio->free(sp);
}

int
@@ -190,20 +208,22 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
{
	struct qla_hw_data *ha = vha->hw;
	srb_t *sp;
	struct srb_logio *lio;
	struct srb_ctx *ctx;
	struct srb_iocb *lio;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    ELS_TMO_2_RATOV(ha) + 2);
	if (!sp)
		goto done;

	lio = sp->ctx;
	lio->ctx.type = SRB_LOGOUT_CMD;
	lio->ctx.name = "logout";
	lio->ctx.timeout = qla2x00_async_logio_timeout;
	lio->ctx.done = qla2x00_async_logout_ctx_done;
	ctx = sp->ctx;
	ctx->type = SRB_LOGOUT_CMD;
	ctx->name = "logout";
	lio = ctx->u.iocb_cmd;
	lio->timeout = qla2x00_async_logio_timeout;
	lio->done = qla2x00_async_logout_ctx_done;
	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
		goto done_free_sp;
@@ -215,8 +235,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
	return rval;

done_free_sp:
	del_timer_sync(&lio->ctx.timer);
	lio->ctx.free(sp);
	lio->free(sp);
done:
	return rval;
}
@@ -224,11 +243,12 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
static void
qla2x00_async_adisc_ctx_done(srb_t *sp)
{
	struct srb_logio *lio = sp->ctx;
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;

	qla2x00_post_async_adisc_done_work(sp->fcport->vha, sp->fcport,
	    lio->data);
	lio->ctx.free(sp);
	    lio->u.logio.data);
	lio->free(sp);
}

int
@@ -237,22 +257,24 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
{
	struct qla_hw_data *ha = vha->hw;
	srb_t *sp;
	struct srb_logio *lio;
	struct srb_ctx *ctx;
	struct srb_iocb *lio;
	int rval;

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_logio),
	sp = qla2x00_get_ctx_sp(vha, fcport, sizeof(struct srb_ctx),
	    ELS_TMO_2_RATOV(ha) + 2);
	if (!sp)
		goto done;

	lio = sp->ctx;
	lio->ctx.type = SRB_ADISC_CMD;
	lio->ctx.name = "adisc";
	lio->ctx.timeout = qla2x00_async_logio_timeout;
	lio->ctx.done = qla2x00_async_adisc_ctx_done;
	ctx = sp->ctx;
	ctx->type = SRB_ADISC_CMD;
	ctx->name = "adisc";
	lio = ctx->u.iocb_cmd;
	lio->timeout = qla2x00_async_logio_timeout;
	lio->done = qla2x00_async_adisc_ctx_done;
	if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
		lio->flags |= SRB_LOGIN_RETRIED;
		lio->u.logio.flags |= SRB_LOGIN_RETRIED;
	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
		goto done_free_sp;
@@ -265,13 +287,12 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
	return rval;

done_free_sp:
	del_timer_sync(&lio->ctx.timer);
	lio->ctx.free(sp);
	lio->free(sp);
done:
	return rval;
}

int
void
qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
    uint16_t *data)
{
@@ -308,25 +329,25 @@ qla2x00_async_login_done(struct scsi_qla_host *vha, fc_port_t *fcport,
		qla2x00_post_async_login_work(vha, fcport, NULL);
		break;
	}
	return QLA_SUCCESS;
	return;
}

int
void
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
    uint16_t *data)
{
	qla2x00_mark_device_lost(vha, fcport, 1, 0);
	return QLA_SUCCESS;
	return;
}

int
void
qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
    uint16_t *data)
{
	if (data[0] == MBS_COMMAND_COMPLETE) {
		qla2x00_update_fcport(vha, fcport);

		return QLA_SUCCESS;
		return;
	}

	/* Retry login. */
@@ -336,7 +357,7 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
	else
		qla2x00_mark_device_lost(vha, fcport, 1, 0);

	return QLA_SUCCESS;
	return;
}

/****************************************************************************/
+14 −10
Original line number Diff line number Diff line
@@ -983,13 +983,14 @@ qla2x00_start_iocbs(srb_t *sp)
static void
qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
{
	struct srb_logio *lio = sp->ctx;
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;

	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
	logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
	if (lio->flags & SRB_LOGIN_COND_PLOGI)
	if (lio->u.logio.flags & SRB_LOGIN_COND_PLOGI)
		logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
	if (lio->flags & SRB_LOGIN_SKIP_PRLI)
	if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI)
		logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI);
	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
	logio->port_id[0] = sp->fcport->d_id.b.al_pa;
@@ -1002,14 +1003,15 @@ static void
qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
{
	struct qla_hw_data *ha = sp->fcport->vha->hw;
	struct srb_logio *lio = sp->ctx;
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *lio = ctx->u.iocb_cmd;
	uint16_t opts;

	mbx->entry_type = MBX_IOCB_TYPE;;
	SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id);
	mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT);
	opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0;
	opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0;
	opts = lio->u.logio.flags & SRB_LOGIN_COND_PLOGI ? BIT_0 : 0;
	opts |= lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI ? BIT_1 : 0;
	if (HAS_EXTENDED_IDS(ha)) {
		mbx->mb1 = cpu_to_le16(sp->fcport->loop_id);
		mbx->mb10 = cpu_to_le16(opts);
@@ -1086,7 +1088,7 @@ qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx)
static void
qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
{
	struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job;
	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;

        els_iocb->entry_type = ELS_IOCB_TYPE;
        els_iocb->entry_count = 1;
@@ -1099,8 +1101,10 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
        els_iocb->sof_type = EST_SOFI3;
        els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt);

        els_iocb->opcode =(((struct srb_bsg*)sp->ctx)->ctx.type == SRB_ELS_CMD_RPT) ?
	    bsg_job->request->rqst_data.r_els.els_code : bsg_job->request->rqst_data.h_els.command_code;
	els_iocb->opcode =
	    (((struct srb_ctx *)sp->ctx)->type == SRB_ELS_CMD_RPT) ?
	    bsg_job->request->rqst_data.r_els.els_code :
	    bsg_job->request->rqst_data.h_els.command_code;
        els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa;
        els_iocb->port_id[1] = sp->fcport->d_id.b.area;
        els_iocb->port_id[2] = sp->fcport->d_id.b.domain;
@@ -1134,7 +1138,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb)
	int index;
	uint16_t tot_dsds;
        scsi_qla_host_t *vha = sp->fcport->vha;
	struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job;
	struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job;
	int loop_iterartion = 0;
	int cont_iocb_prsnt = 0;
	int entry_count = 1;
Loading