From 3480e7a8c8e47a6ee101ab722c58d61761b67e4a Mon Sep 17 00:00:00 2001 From: Saurav Kashyap Date: Fri, 23 Aug 2019 02:52:43 -0700 Subject: [PATCH] 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: Saurav Kashyap Signed-off-by: Martin K. Petersen --- drivers/scsi/qedf/qedf_main.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index 0856d136bab6..9c24f3834d70 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -111,16 +111,18 @@ static struct kmem_cache *qedf_io_work_cache; void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id) { - qedf->vlan_id = vlan_id; - qedf->vlan_id |= qedf->prio << VLAN_PRIO_SHIFT; - QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Setting vlan_id=%04x " - "prio=%d.\n", vlan_id, qedf->prio); + int vlan_id_tmp = 0; + + vlan_id_tmp = vlan_id | (qedf->prio << VLAN_PRIO_SHIFT); + 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 */ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) { - int rc; while (qedf->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) if (qedf->vlan_id > 0) { 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; } @@ -144,13 +149,7 @@ static bool qedf_initiate_fipvlan_req(struct qedf_ctx *qedf) "Retry %d.\n", qedf->fipvlan_retries); init_completion(&qedf->fipvlan_compl); qedf_fcoe_send_vlan_req(qedf); - rc = wait_for_completion_timeout(&qedf->fipvlan_compl, - 1 * HZ); - if (rc > 0 && - (atomic_read(&qedf->link_state) == QEDF_LINK_UP)) { - fcoe_ctlr_link_up(&qedf->ctlr); - return true; - } + wait_for_completion_timeout(&qedf->fipvlan_compl, 1 * HZ); } return false;