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

Commit 2d73ac61 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Serialize GPNID for multiple RSCN



GPNID is triggered by RSCN. For multiple RSCNs of the same affected
NPORT ID, serialize the GPNID to prevent confusion.

Fixes: 726b8548 ("qla2xxx: Add framework for async fabric discovery")
Cc: <stable@vger.kernel.org> # 4.10+
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 25ad76b7
Loading
Loading
Loading
Loading
+26 −22
Original line number Diff line number Diff line
@@ -315,6 +315,29 @@ struct srb_cmd {
/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
#define IS_PROT_IO(sp)	(sp->flags & SRB_CRC_CTX_DSD_VALID)

/*
 * 24 bit port ID type definition.
 */
typedef union {
	uint32_t b24 : 24;

	struct {
#ifdef __BIG_ENDIAN
		uint8_t domain;
		uint8_t area;
		uint8_t al_pa;
#elif defined(__LITTLE_ENDIAN)
		uint8_t al_pa;
		uint8_t area;
		uint8_t domain;
#else
#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
#endif
		uint8_t rsvd_1;
	} b;
} port_id_t;
#define INVALID_PORT_ID	0xFFFFFF

struct els_logo_payload {
	uint8_t opcode;
	uint8_t rsvd[3];
@@ -338,6 +361,7 @@ struct ct_arg {
	u32		rsp_size;
	void		*req;
	void		*rsp;
	port_id_t	id;
};

/*
@@ -499,6 +523,7 @@ typedef struct srb {
	const char *name;
	int iocbs;
	struct qla_qpair *qpair;
	struct list_head elem;
	u32 gen1;	/* scratch */
	u32 gen2;	/* scratch */
	union {
@@ -2164,28 +2189,6 @@ struct imm_ntfy_from_isp {
#define REQUEST_ENTRY_SIZE	(sizeof(request_t))


/*
 * 24 bit port ID type definition.
 */
typedef union {
	uint32_t b24 : 24;

	struct {
#ifdef __BIG_ENDIAN
		uint8_t domain;
		uint8_t area;
		uint8_t al_pa;
#elif defined(__LITTLE_ENDIAN)
		uint8_t al_pa;
		uint8_t area;
		uint8_t domain;
#else
#error "__BIG_ENDIAN or __LITTLE_ENDIAN must be defined!"
#endif
		uint8_t rsvd_1;
	} b;
} port_id_t;
#define INVALID_PORT_ID	0xFFFFFF

/*
 * Switch info gathering structure.
@@ -4252,6 +4255,7 @@ typedef struct scsi_qla_host {
	uint8_t n2n_node_name[WWN_SIZE];
	uint8_t n2n_port_name[WWN_SIZE];
	uint16_t	n2n_id;
	struct list_head gpnid_list;
} scsi_qla_host_t;

struct qla27xx_image_status {
+30 −5
Original line number Diff line number Diff line
@@ -3221,16 +3221,17 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
	    (struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp;
	struct event_arg ea;
	struct qla_work_evt *e;
	unsigned long flags;

	if (res)
		ql_dbg(ql_dbg_disc, vha, 0x2066,
		    "Async done-%s fail res %x ID %3phC. %8phC\n",
		    sp->name, res, ct_req->req.port_id.port_id,
		    "Async done-%s fail res %x rscn gen %d ID %3phC. %8phC\n",
		    sp->name, res, sp->gen1, ct_req->req.port_id.port_id,
		    ct_rsp->rsp.gpn_id.port_name);
	else
		ql_dbg(ql_dbg_disc, vha, 0x2066,
		    "Async done-%s good ID %3phC. %8phC\n",
		    sp->name, ct_req->req.port_id.port_id,
		    "Async done-%s good rscn gen %d ID %3phC. %8phC\n",
		    sp->name, sp->gen1, ct_req->req.port_id.port_id,
		    ct_rsp->rsp.gpn_id.port_name);

	memset(&ea, 0, sizeof(ea));
@@ -3242,11 +3243,20 @@ static void qla2x00_async_gpnid_sp_done(void *s, int res)
	ea.rc = res;
	ea.event = FCME_GPNID_DONE;

	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
	list_del(&sp->elem);
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);

	if (res) {
		if (res == QLA_FUNCTION_TIMEOUT)
			qla24xx_post_gpnid_work(sp->vha, &ea.id);
		sp->free(sp);
		return;
	} else if (sp->gen1) {
		/* There was anoter RSNC for this Nport ID */
		qla24xx_post_gpnid_work(sp->vha, &ea.id);
		sp->free(sp);
		return;
	}

	qla2x00_fcport_event_handler(vha, &ea);
@@ -3282,8 +3292,9 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)
{
	int rval = QLA_FUNCTION_FAILED;
	struct ct_sns_req       *ct_req;
	srb_t *sp;
	srb_t *sp, *tsp;
	struct ct_sns_pkt *ct_sns;
	unsigned long flags;

	if (!vha->flags.online)
		goto done;
@@ -3294,8 +3305,22 @@ int qla24xx_async_gpnid(scsi_qla_host_t *vha, port_id_t *id)

	sp->type = SRB_CT_PTHRU_CMD;
	sp->name = "gpnid";
	sp->u.iocb_cmd.u.ctarg.id = *id;
	sp->gen1 = 0;
	qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);

	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
	list_for_each_entry(tsp, &vha->gpnid_list, elem) {
		if (tsp->u.iocb_cmd.u.ctarg.id.b24 == id->b24) {
			tsp->gen1++;
			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
			sp->free(sp);
			goto done;
		}
	}
	list_add_tail(&sp->elem, &vha->gpnid_list);
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);

	sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
		sizeof(struct ct_sns_pkt), &sp->u.iocb_cmd.u.ctarg.req_dma,
		GFP_KERNEL);
+1 −1
Original line number Diff line number Diff line
@@ -1574,7 +1574,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req,
		/* borrowing sts_entry_24xx.comp_status.
		   same location as ct_entry_24xx.comp_status
		 */
		res = qla2x00_chk_ms_status(vha, (ms_iocb_entry_t *)pkt,
		res = qla2x00_chk_ms_status(sp->vha, (ms_iocb_entry_t *)pkt,
			(struct ct_sns_rsp *)sp->u.iocb_cmd.u.ctarg.rsp,
			sp->name);
		sp->done(sp, res);
+1 −0
Original line number Diff line number Diff line
@@ -4515,6 +4515,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
	INIT_LIST_HEAD(&vha->qp_list);
	INIT_LIST_HEAD(&vha->gnl.fcports);
	INIT_LIST_HEAD(&vha->nvme_rport_list);
	INIT_LIST_HEAD(&vha->gpnid_list);

	spin_lock_init(&vha->work_lock);
	spin_lock_init(&vha->cmd_list_lock);