Commit 92d685a9 authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

Merge patch series "qla2xxx driver update"

Nilesh Javali <njavali@marvell.com> says:

Please apply the qla2xxx driver enhancement and bug fixes to the scsi tree
at your earliest convenience.

Link: https://lore.kernel.org/r/20230428075339.32551-1-njavali@marvell.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents 808e87a5 eb91eb80
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -2750,6 +2750,7 @@ static void
qla2x00_terminate_rport_io(struct fc_rport *rport)
{
	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
	scsi_qla_host_t *vha;

	if (!fcport)
		return;
@@ -2759,9 +2760,12 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)

	if (test_bit(ABORT_ISP_ACTIVE, &fcport->vha->dpc_flags))
		return;
	vha = fcport->vha;

	if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
		qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
		qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
			0, WAIT_TARGET);
		return;
	}
	/*
@@ -2786,6 +2790,15 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
			qla2x00_port_logout(fcport->vha, fcport);
		}
	}

	/* check for any straggling io left behind */
	if (qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24, 0, WAIT_TARGET)) {
		ql_log(ql_log_warn, vha, 0x300b,
		       "IO not return.  Resetting. \n");
		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
		qla2xxx_wake_dpc(vha);
		qla2x00_wait_for_chip_reset(vha);
	}
}

static int
+21 −0
Original line number Diff line number Diff line
@@ -465,6 +465,15 @@ static inline be_id_t port_id_to_be_id(port_id_t port_id)
	return res;
}

struct tmf_arg {
	struct qla_qpair *qpair;
	struct fc_port *fcport;
	struct scsi_qla_host *vha;
	u64 lun;
	u32 flags;
	uint8_t modifier;
};

struct els_logo_payload {
	uint8_t opcode;
	uint8_t rsvd[3];
@@ -544,6 +553,10 @@ struct srb_iocb {
			uint32_t data;
			struct completion comp;
			__le16 comp_status;

			uint8_t modifier;
			uint8_t vp_index;
			uint16_t loop_id;
		} tmf;
		struct {
#define SRB_FXDISC_REQ_DMA_VALID	BIT_0
@@ -647,6 +660,7 @@ struct srb_iocb {
#define SRB_SA_UPDATE	25
#define SRB_ELS_CMD_HST_NOLOGIN 26
#define SRB_SA_REPLACE	27
#define SRB_MARKER	28

struct qla_els_pt_arg {
	u8 els_opcode;
@@ -2528,6 +2542,7 @@ enum rscn_addr_format {
typedef struct fc_port {
	struct list_head list;
	struct scsi_qla_host *vha;
	struct list_head tmf_pending;

	unsigned int conf_compl_supported:1;
	unsigned int deleted:2;
@@ -2548,6 +2563,8 @@ typedef struct fc_port {
	unsigned int do_prli_nvme:1;

	uint8_t nvme_flag;
	uint8_t active_tmf;
#define MAX_ACTIVE_TMF 8

	uint8_t node_name[WWN_SIZE];
	uint8_t port_name[WWN_SIZE];
@@ -5498,4 +5515,8 @@ struct ql_vnd_tgt_stats_resp {
	_fp->disc_state, _fp->scan_state, _fp->loop_id, _fp->deleted, \
	_fp->flags

#define TMF_NOT_READY(_fcport) \
	(!_fcport || IS_SESSION_DELETED(_fcport) || atomic_read(&_fcport->state) != FCS_ONLINE || \
	!_fcport->vha->hw->flags.fw_started)

#endif
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ 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);
extern int qla2x00_async_tm_cmd(fc_port_t *, uint32_t, uint64_t, uint32_t);
struct qla_work_evt *qla2x00_alloc_work(struct scsi_qla_host *,
    enum qla_work_type);
extern int qla24xx_async_gnl(struct scsi_qla_host *, fc_port_t *);
+236 −20
Original line number Diff line number Diff line
@@ -1996,6 +1996,11 @@ qla2x00_tmf_iocb_timeout(void *data)
	int rc, h;
	unsigned long flags;

	if (sp->type == SRB_MARKER) {
		complete(&tmf->u.tmf.comp);
		return;
	}

	rc = qla24xx_async_abort_cmd(sp, false);
	if (rc) {
		spin_lock_irqsave(sp->qpair->qp_lock_ptr, flags);
@@ -2013,24 +2018,131 @@ qla2x00_tmf_iocb_timeout(void *data)
	}
}

static void qla_marker_sp_done(srb_t *sp, int res)
{
	struct srb_iocb *tmf = &sp->u.iocb_cmd;

	if (res != QLA_SUCCESS)
		ql_dbg(ql_dbg_taskm, sp->vha, 0x8004,
		    "Async-marker fail hdl=%x portid=%06x ctrl=%x lun=%lld qp=%d.\n",
		    sp->handle, sp->fcport->d_id.b24, sp->u.iocb_cmd.u.tmf.flags,
		    sp->u.iocb_cmd.u.tmf.lun, sp->qpair->id);

	sp->u.iocb_cmd.u.tmf.data = res;
	complete(&tmf->u.tmf.comp);
}

#define  START_SP_W_RETRIES(_sp, _rval) \
{\
	int cnt = 5; \
	do { \
		_rval = qla2x00_start_sp(_sp); \
		if (_rval == EAGAIN) \
			msleep(1); \
		else \
			break; \
		cnt--; \
	} while (cnt); \
}

/**
 * qla26xx_marker: send marker IOCB and wait for the completion of it.
 * @arg: pointer to argument list.
 *    It is assume caller will provide an fcport pointer and modifier
 */
static int
qla26xx_marker(struct tmf_arg *arg)
{
	struct scsi_qla_host *vha = arg->vha;
	struct srb_iocb *tm_iocb;
	srb_t *sp;
	int rval = QLA_FUNCTION_FAILED;
	fc_port_t *fcport = arg->fcport;

	if (TMF_NOT_READY(arg->fcport)) {
		ql_dbg(ql_dbg_taskm, vha, 0x8039,
		    "FC port not ready for marker loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n",
		    fcport->loop_id, fcport->d_id.b24,
		    arg->modifier, arg->lun, arg->qpair->id);
		return QLA_SUSPENDED;
	}

	/* ref: INIT */
	sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	sp->type = SRB_MARKER;
	sp->name = "marker";
	qla2x00_init_async_sp(sp, qla2x00_get_async_timeout(vha), qla_marker_sp_done);
	sp->u.iocb_cmd.timeout = qla2x00_tmf_iocb_timeout;

	tm_iocb = &sp->u.iocb_cmd;
	init_completion(&tm_iocb->u.tmf.comp);
	tm_iocb->u.tmf.modifier = arg->modifier;
	tm_iocb->u.tmf.lun = arg->lun;
	tm_iocb->u.tmf.loop_id = fcport->loop_id;
	tm_iocb->u.tmf.vp_index = vha->vp_idx;

	START_SP_W_RETRIES(sp, rval);

	ql_dbg(ql_dbg_taskm, vha, 0x8006,
	    "Async-marker hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
	    sp->handle, fcport->loop_id, fcport->d_id.b24,
	    arg->modifier, arg->lun, sp->qpair->id, rval);

	if (rval != QLA_SUCCESS) {
		ql_log(ql_log_warn, vha, 0x8031,
		    "Marker IOCB send failure (%x).\n", rval);
		goto done_free_sp;
	}

	wait_for_completion(&tm_iocb->u.tmf.comp);
	rval = tm_iocb->u.tmf.data;

	if (rval != QLA_SUCCESS) {
		ql_log(ql_log_warn, vha, 0x8019,
		    "Marker failed hdl=%x loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d rval %d.\n",
		    sp->handle, fcport->loop_id, fcport->d_id.b24,
		    arg->modifier, arg->lun, sp->qpair->id, rval);
	}

done_free_sp:
	/* ref: INIT */
	kref_put(&sp->cmd_kref, qla2x00_sp_release);
done:
	return rval;
}

static void qla2x00_tmf_sp_done(srb_t *sp, int res)
{
	struct srb_iocb *tmf = &sp->u.iocb_cmd;

	if (res)
		tmf->u.tmf.data = res;
	complete(&tmf->u.tmf.comp);
}

int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
	uint32_t tag)
static int
__qla2x00_async_tm_cmd(struct tmf_arg *arg)
{
	struct scsi_qla_host *vha = fcport->vha;
	struct scsi_qla_host *vha = arg->vha;
	struct srb_iocb *tm_iocb;
	srb_t *sp;
	int rval = QLA_FUNCTION_FAILED;

	fc_port_t *fcport = arg->fcport;

	if (TMF_NOT_READY(arg->fcport)) {
		ql_dbg(ql_dbg_taskm, vha, 0x8032,
		    "FC port not ready for TM command loop-id=%x portid=%06x modifier=%x lun=%lld qp=%d.\n",
		    fcport->loop_id, fcport->d_id.b24,
		    arg->modifier, arg->lun, arg->qpair->id);
		return QLA_SUSPENDED;
	}

	/* ref: INIT */
	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	sp = qla2xxx_get_qpair_sp(vha, arg->qpair, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

@@ -2043,15 +2155,16 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,

	tm_iocb = &sp->u.iocb_cmd;
	init_completion(&tm_iocb->u.tmf.comp);
	tm_iocb->u.tmf.flags = flags;
	tm_iocb->u.tmf.lun = lun;
	tm_iocb->u.tmf.flags = arg->flags;
	tm_iocb->u.tmf.lun = arg->lun;

	START_SP_W_RETRIES(sp, rval);

	ql_dbg(ql_dbg_taskm, vha, 0x802f,
	    "Async-tmf 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);
	    "Async-tmf hdl=%x loop-id=%x portid=%06x ctrl=%x lun=%lld qp=%d rval=%x.\n",
	    sp->handle, fcport->loop_id, fcport->d_id.b24,
	    arg->flags, arg->lun, sp->qpair->id, rval);

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
		goto done_free_sp;
	wait_for_completion(&tm_iocb->u.tmf.comp);
@@ -2063,15 +2176,8 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
		    "TM IOCB failed (%x).\n", rval);
	}

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

		/* Issue Marker IOCB */
		qla2x00_marker(vha, vha->hw->base_qpair,
		    fcport->loop_id, lun,
		    flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
	}
	if (!test_bit(UNLOADING, &vha->dpc_flags) && !IS_QLAFX00(vha->hw))
		rval = qla26xx_marker(arg);

done_free_sp:
	/* ref: INIT */
@@ -2080,6 +2186,115 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
	return rval;
}

static void qla_put_tmf(fc_port_t *fcport)
{
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	unsigned long flags;

	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
	fcport->active_tmf--;
	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
}

static
int qla_get_tmf(fc_port_t *fcport)
{
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	unsigned long flags;
	int rc = 0;
	LIST_HEAD(tmf_elem);

	spin_lock_irqsave(&ha->tgt.sess_lock, flags);
	list_add_tail(&tmf_elem, &fcport->tmf_pending);

	while (fcport->active_tmf >= MAX_ACTIVE_TMF) {
		spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);

		msleep(1);

		spin_lock_irqsave(&ha->tgt.sess_lock, flags);
		if (TMF_NOT_READY(fcport)) {
			ql_log(ql_log_warn, vha, 0x802c,
			    "Unable to acquire TM resource due to disruption.\n");
			rc = EIO;
			break;
		}
		if (fcport->active_tmf < MAX_ACTIVE_TMF &&
		    list_is_first(&tmf_elem, &fcport->tmf_pending))
			break;
	}

	list_del(&tmf_elem);

	if (!rc)
		fcport->active_tmf++;

	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);

	return rc;
}

int
qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint64_t lun,
		     uint32_t tag)
{
	struct scsi_qla_host *vha = fcport->vha;
	struct qla_qpair *qpair;
	struct tmf_arg a;
	int i, rval = QLA_SUCCESS;

	if (TMF_NOT_READY(fcport))
		return QLA_SUSPENDED;

	a.vha = fcport->vha;
	a.fcport = fcport;
	a.lun = lun;
	if (flags & (TCF_LUN_RESET|TCF_ABORT_TASK_SET|TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
		a.modifier = MK_SYNC_ID_LUN;

		if (qla_get_tmf(fcport))
			return QLA_FUNCTION_FAILED;
	} else {
		a.modifier = MK_SYNC_ID;
	}

	if (vha->hw->mqenable) {
		for (i = 0; i < vha->hw->num_qpairs; i++) {
			qpair = vha->hw->queue_pair_map[i];
			if (!qpair)
				continue;

			if (TMF_NOT_READY(fcport)) {
				ql_log(ql_log_warn, vha, 0x8026,
				    "Unable to send TM due to disruption.\n");
				rval = QLA_SUSPENDED;
				break;
			}

			a.qpair = qpair;
			a.flags = flags|TCF_NOTMCMD_TO_TARGET;
			rval = __qla2x00_async_tm_cmd(&a);
			if (rval)
				break;
		}
	}

	if (rval)
		goto bailout;

	a.qpair = vha->hw->base_qpair;
	a.flags = flags;
	rval = __qla2x00_async_tm_cmd(&a);

bailout:
	if (a.modifier == MK_SYNC_ID_LUN)
		qla_put_tmf(fcport);

	return rval;
}

int
qla24xx_async_abort_command(srb_t *sp)
{
@@ -5291,6 +5506,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
	INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
	INIT_LIST_HEAD(&fcport->gnl_entry);
	INIT_LIST_HEAD(&fcport->list);
	INIT_LIST_HEAD(&fcport->tmf_pending);

	INIT_LIST_HEAD(&fcport->sess_cmd_list);
	spin_lock_init(&fcport->sess_cmd_lock);
+27 −6
Original line number Diff line number Diff line
@@ -522,21 +522,25 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair,
		return (QLA_FUNCTION_FAILED);
	}

	mrk24 = (struct mrk_entry_24xx *)mrk;

	mrk->entry_type = MARKER_TYPE;
	mrk->modifier = type;
	if (type != MK_SYNC_ALL) {
		if (IS_FWI2_CAPABLE(ha)) {
			mrk24 = (struct mrk_entry_24xx *) mrk;
			mrk24->nport_handle = cpu_to_le16(loop_id);
			int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun);
			host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun));
			mrk24->vp_index = vha->vp_idx;
			mrk24->handle = make_handle(req->id, mrk24->handle);
		} else {
			SET_TARGET_ID(ha, mrk->target, loop_id);
			mrk->lun = cpu_to_le16((uint16_t)lun);
		}
	}

	if (IS_FWI2_CAPABLE(ha))
		mrk24->handle = QLA_SKIP_HANDLE;

	wmb();

	qla2x00_start_iocbs(vha, req);
@@ -2541,7 +2545,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
	scsi_qla_host_t *vha = fcport->vha;
	struct qla_hw_data *ha = vha->hw;
	struct srb_iocb *iocb = &sp->u.iocb_cmd;
	struct req_que *req = vha->req;
	struct req_que *req = sp->qpair->req;

	flags = iocb->u.tmf.flags;
	lun = iocb->u.tmf.lun;
@@ -2557,7 +2561,8 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk)
	tsk->port_id[2] = fcport->d_id.b.domain;
	tsk->vp_index = fcport->vha->vp_idx;

	if (flags == TCF_LUN_RESET) {
	if (flags & (TCF_LUN_RESET | TCF_ABORT_TASK_SET|
	    TCF_CLEAR_TASK_SET|TCF_CLEAR_ACA)) {
		int_to_scsilun(lun, &tsk->lun);
		host_to_fcp_swap((uint8_t *)&tsk->lun,
			sizeof(tsk->lun));
@@ -3852,9 +3857,9 @@ static int qla_get_iocbs_resource(struct srb *sp)
	case SRB_NACK_LOGO:
	case SRB_LOGOUT_CMD:
	case SRB_CTRL_VP:
		push_it_through = true;
		fallthrough;
	case SRB_MARKER:
	default:
		push_it_through = true;
		get_exch = false;
	}

@@ -3870,6 +3875,19 @@ static int qla_get_iocbs_resource(struct srb *sp)
	return qla_get_fw_resources(sp->qpair, &sp->iores);
}

static void
qla_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk)
{
	mrk->entry_type = MARKER_TYPE;
	mrk->modifier = sp->u.iocb_cmd.u.tmf.modifier;
	if (sp->u.iocb_cmd.u.tmf.modifier != MK_SYNC_ALL) {
		mrk->nport_handle = cpu_to_le16(sp->u.iocb_cmd.u.tmf.loop_id);
		int_to_scsilun(sp->u.iocb_cmd.u.tmf.lun, (struct scsi_lun *)&mrk->lun);
		host_to_fcp_swap(mrk->lun, sizeof(mrk->lun));
		mrk->vp_index = sp->u.iocb_cmd.u.tmf.vp_index;
	}
}

int
qla2x00_start_sp(srb_t *sp)
{
@@ -3973,6 +3991,9 @@ qla2x00_start_sp(srb_t *sp)
	case SRB_SA_REPLACE:
		qla24xx_sa_replace_iocb(sp, pkt);
		break;
	case SRB_MARKER:
		qla_marker_iocb(sp, pkt);
		break;
	default:
		break;
	}
Loading