Commit 3480e7a8 authored by Saurav Kashyap's avatar Saurav Kashyap Committed by Martin K. Petersen

scsi: qedf: Fix race betwen fipvlan request and response path

There is a race b/w fipvlan request and response path:

=====
qedf_fcoe_process_vlan_resp:113]:2: VLAN response, vid=0xffd.
qedf_initiate_fipvlan_req:165]:2: vlan = 0x6ffd already set.
qedf_set_vlan_id:139]:2: Setting vlan_id=0ffd prio=3.
======

The request thread sees that vlan is already set and fails to call
ctrl_link_up.

Fix:

 - While setting vlan_id use local variable and before setting vlan_id.

 - Call fcoe_ctlr_link_up in next iteration of fipvlan request.
Signed-off-by: default avatarSaurav Kashyap <skashyap@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 5797bcc8
...@@ -111,16 +111,18 @@ static struct kmem_cache *qedf_io_work_cache; ...@@ -111,16 +111,18 @@ static struct kmem_cache *qedf_io_work_cache;
void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id) void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id)
{ {
qedf->vlan_id = vlan_id; int vlan_id_tmp = 0;
qedf->vlan_id |= qedf->prio << VLAN_PRIO_SHIFT;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Setting vlan_id=%04x " vlan_id_tmp = vlan_id | (qedf->prio << VLAN_PRIO_SHIFT);
"prio=%d.\n", vlan_id, qedf->prio); qedf->vlan_id = vlan_id_tmp;
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"Setting vlan_id=0x%04x prio=%d.\n",
vlan_id_tmp, qedf->prio);
} }
/* Returns true if we have a valid vlan, false otherwise */ /* Returns true if we have a valid vlan, false otherwise */
static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf)
{ {
int rc;
while (qedf->fipvlan_retries--) { while (qedf->fipvlan_retries--) {
/* This is to catch if link goes down during fipvlan retries */ /* This is to catch if link goes down during fipvlan retries */
...@@ -136,7 +138,10 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) ...@@ -136,7 +138,10 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf)
if (qedf->vlan_id > 0) { if (qedf->vlan_id > 0) {
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC, QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_DISC,
"vlan = 0x%x already set.\n", qedf->vlan_id); "vlan = 0x%x already set, calling ctlr_link_up.\n",
qedf->vlan_id);
if (atomic_read(&qedf->link_state) == QEDF_LINK_UP)
fcoe_ctlr_link_up(&qedf->ctlr);
return true; return true;
} }
...@@ -144,13 +149,7 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) ...@@ -144,13 +149,7 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf)
"Retry %d.\n", qedf->fipvlan_retries); "Retry %d.\n", qedf->fipvlan_retries);
init_completion(&qedf->fipvlan_compl); init_completion(&qedf->fipvlan_compl);
qedf_fcoe_send_vlan_req(qedf); qedf_fcoe_send_vlan_req(qedf);
rc = wait_for_completion_timeout(&qedf->fipvlan_compl, wait_for_completion_timeout(&qedf->fipvlan_compl, 1 * HZ);
1 * HZ);
if (rc > 0 &&
(atomic_read(&qedf->link_state) == QEDF_LINK_UP)) {
fcoe_ctlr_link_up(&qedf->ctlr);
return true;
}
} }
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment