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

Commit 11aea16a authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Add ability to send PRLO



Add ability to send Implicit PRLO to flush IOs
from FW back to driver.

Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9ecf0b0d
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -507,6 +507,7 @@ struct srb_iocb {
#define SRB_NVME_LS	20
#define SRB_PRLI_CMD	21
#define SRB_CTRL_VP	22
#define SRB_PRLO_CMD	23

enum {
	TYPE_SRB,
@@ -3140,6 +3141,8 @@ enum qla_work_type {
	QLA_EVT_GNL,
	QLA_EVT_NACK,
	QLA_EVT_RELOGIN,
	QLA_EVT_ASYNC_PRLO,
	QLA_EVT_ASYNC_PRLO_DONE,
};


+8 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ extern void qla84xx_put_chip(struct scsi_qla_host *);
extern int qla2x00_async_login(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_async_logout(struct scsi_qla_host *, fc_port_t *);
extern int qla2x00_async_prlo(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_tm_cmd(fc_port_t *, uint32_t, uint32_t, uint32_t);
@@ -109,6 +110,13 @@ int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
int qla24xx_fcport_handle_login(struct scsi_qla_host *, fc_port_t *);
int qla24xx_detect_sfp(scsi_qla_host_t *vha);
int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
void qla2x00_async_prlo_done(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
    uint16_t *);
extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *,
    fc_port_t *, uint16_t *);

/*
 * Global Data in qla_os.c source file.
 */
+59 −0
Original line number Diff line number Diff line
@@ -278,6 +278,65 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t *fcport)
	fcport->flags &= ~FCF_ASYNC_SENT;
	return rval;
}

void
qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
    uint16_t *data)
{
	/* Don't re-login in target mode */
	if (!fcport->tgt_session)
		qla2x00_mark_device_lost(vha, fcport, 1, 0);
	qlt_logo_completion_handler(fcport, data[0]);
}

static void
qla2x00_async_prlo_sp_done(void *s, int res)
{
	srb_t *sp = (srb_t *)s;
	struct srb_iocb *lio = &sp->u.iocb_cmd;
	struct scsi_qla_host *vha = sp->vha;

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

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

	rval = QLA_FUNCTION_FAILED;
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	sp->type = SRB_PRLO_CMD;
	sp->name = "prlo";
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	lio = &sp->u.iocb_cmd;
	lio->timeout = qla2x00_async_iocb_timeout;
	sp->done = qla2x00_async_prlo_sp_done;
	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
		goto done_free_sp;

	ql_dbg(ql_dbg_disc, vha, 0x2070,
	    "Async-prlo - hdl=%x loop-id=%x portid=%02x%02x%02x.\n",
	    sp->handle, fcport->loop_id, fcport->d_id.b.domain,
	    fcport->d_id.b.area, fcport->d_id.b.al_pa);
	return rval;

done_free_sp:
	sp->free(sp);
done:
	return rval;
}

static
void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
{
+17 −0
Original line number Diff line number Diff line
@@ -3390,6 +3390,20 @@ qla25xx_ctrlvp_iocb(srb_t *sp, struct vp_ctrl_entry_24xx *vce)
	vce->vp_idx_map[map] |= 1 << pos;
}

static void
qla24xx_prlo_iocb(srb_t *sp, struct logio_entry_24xx *logio)
{
	logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
	logio->control_flags =
	    cpu_to_le16(LCF_COMMAND_PRLO|LCF_IMPL_PRLO);

	logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
	logio->port_id[0] = sp->fcport->d_id.b.al_pa;
	logio->port_id[1] = sp->fcport->d_id.b.area;
	logio->port_id[2] = sp->fcport->d_id.b.domain;
	logio->vp_index = sp->fcport->vha->vp_idx;
}

int
qla2x00_start_sp(srb_t *sp)
{
@@ -3471,6 +3485,9 @@ qla2x00_start_sp(srb_t *sp)
	case SRB_CTRL_VP:
		qla25xx_ctrlvp_iocb(sp, pkt);
		break;
	case SRB_PRLO_CMD:
		qla24xx_prlo_iocb(sp, pkt);
		break;
	default:
		break;
	}
+9 −0
Original line number Diff line number Diff line
@@ -4690,6 +4690,8 @@ qla2x00_post_async_work(logout, QLA_EVT_ASYNC_LOGOUT);
qla2x00_post_async_work(logout_done, QLA_EVT_ASYNC_LOGOUT_DONE);
qla2x00_post_async_work(adisc, QLA_EVT_ASYNC_ADISC);
qla2x00_post_async_work(adisc_done, QLA_EVT_ASYNC_ADISC_DONE);
qla2x00_post_async_work(prlo, QLA_EVT_ASYNC_PRLO);
qla2x00_post_async_work(prlo_done, QLA_EVT_ASYNC_PRLO_DONE);

int
qla2x00_post_uevent_work(struct scsi_qla_host *vha, u32 code)
@@ -4943,6 +4945,13 @@ qla2x00_do_work(struct scsi_qla_host *vha)
		case QLA_EVT_NACK:
			qla24xx_do_nack_work(vha, e);
			break;
		case QLA_EVT_ASYNC_PRLO:
			qla2x00_async_prlo(vha, e->u.logio.fcport);
			break;
		case QLA_EVT_ASYNC_PRLO_DONE:
			qla2x00_async_prlo_done(vha, e->u.logio.fcport,
			    e->u.logio.data);
			break;
		}
		if (e->flags & QLA_EVT_FLAG_FREE)
			kfree(e);