Skip to content

Commit

Permalink
scsi: qla2xxx: Serialize GPNID for multiple RSCN
Browse files Browse the repository at this point in the history
GPNID is triggered by RSCN. For multiple RSCNs of the same affected
NPORT ID, serialize the GPNID to prevent confusion.

Fixes: 726b854 ("qla2xxx: Add framework for async fabric discovery")
Cc: <stable@vger.kernel.org> # 4.10+
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Quinn Tran authored and martinkpetersen committed Dec 8, 2017
1 parent 25ad76b commit 2d73ac6
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 28 deletions.
48 changes: 26 additions & 22 deletions drivers/scsi/qla2xxx/qla_def.h
Expand Up @@ -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];
Expand All @@ -338,6 +361,7 @@ struct ct_arg {
u32 rsp_size;
void *req;
void *rsp;
port_id_t id;
};

/*
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down
35 changes: 30 additions & 5 deletions drivers/scsi/qla2xxx/qla_gs.c
Expand Up @@ -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));
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/qla2xxx/qla_isr.c
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/qla2xxx/qla_os.c
Expand Up @@ -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);
Expand Down

0 comments on commit 2d73ac6

Please sign in to comment.