diff options
author | Saurav Kashyap <skashyap@marvell.com> | 2019-08-23 12:52:43 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-08-30 01:51:19 +0300 |
commit | 3480e7a8c8e47a6ee101ab722c58d61761b67e4a (patch) | |
tree | 777a30c2f1a72f61d81cce2812bc2c234b5fc5fb /drivers/scsi/qedf | |
parent | 5797bcc897c363a775ac3d929b62d2579bdf8573 (diff) | |
download | linux-3480e7a8c8e47a6ee101ab722c58d61761b67e4a.tar.xz |
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 <skashyap@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qedf')
-rw-r--r-- | drivers/scsi/qedf/qedf_main.c | 25 |
1 files 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; |