Commit 7374fbd9 authored by Selvin Xavier's avatar Selvin Xavier Committed by Doug Ledford

RDMA/bnxt_re: Avoid system hang during device un-reg

BNXT_RE_FLAG_TASK_IN_PROG doesn't handle multiple work
requests posted together. Track schedule of multiple
workqueue items by maintaining a per device counter
and proceed with IB dereg only if this counter is zero.
flush_workqueue is no longer required from
NETDEV_UNREGISTER path.
Signed-off-by: default avatarSelvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent dcdaba08
...@@ -120,7 +120,6 @@ struct bnxt_re_dev { ...@@ -120,7 +120,6 @@ struct bnxt_re_dev {
#define BNXT_RE_FLAG_HAVE_L2_REF 3 #define BNXT_RE_FLAG_HAVE_L2_REF 3
#define BNXT_RE_FLAG_RCFW_CHANNEL_EN 4 #define BNXT_RE_FLAG_RCFW_CHANNEL_EN 4
#define BNXT_RE_FLAG_QOS_WORK_REG 5 #define BNXT_RE_FLAG_QOS_WORK_REG 5
#define BNXT_RE_FLAG_TASK_IN_PROG 6
#define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29 #define BNXT_RE_FLAG_ISSUE_ROCE_STATS 29
struct net_device *netdev; struct net_device *netdev;
unsigned int version, major, minor; unsigned int version, major, minor;
...@@ -158,6 +157,7 @@ struct bnxt_re_dev { ...@@ -158,6 +157,7 @@ struct bnxt_re_dev {
atomic_t srq_count; atomic_t srq_count;
atomic_t mr_count; atomic_t mr_count;
atomic_t mw_count; atomic_t mw_count;
atomic_t sched_count;
/* Max of 2 lossless traffic class supported per port */ /* Max of 2 lossless traffic class supported per port */
u16 cosq[2]; u16 cosq[2];
......
...@@ -656,7 +656,6 @@ static void bnxt_re_dev_remove(struct bnxt_re_dev *rdev) ...@@ -656,7 +656,6 @@ static void bnxt_re_dev_remove(struct bnxt_re_dev *rdev)
mutex_unlock(&bnxt_re_dev_lock); mutex_unlock(&bnxt_re_dev_lock);
synchronize_rcu(); synchronize_rcu();
flush_workqueue(bnxt_re_wq);
ib_dealloc_device(&rdev->ibdev); ib_dealloc_device(&rdev->ibdev);
/* rdev is gone */ /* rdev is gone */
...@@ -1441,7 +1440,7 @@ static void bnxt_re_task(struct work_struct *work) ...@@ -1441,7 +1440,7 @@ static void bnxt_re_task(struct work_struct *work)
break; break;
} }
smp_mb__before_atomic(); smp_mb__before_atomic();
clear_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags); atomic_dec(&rdev->sched_count);
kfree(re_work); kfree(re_work);
} }
...@@ -1503,7 +1502,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier, ...@@ -1503,7 +1502,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
/* netdev notifier will call NETDEV_UNREGISTER again later since /* netdev notifier will call NETDEV_UNREGISTER again later since
* we are still holding the reference to the netdev * we are still holding the reference to the netdev
*/ */
if (test_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags)) if (atomic_read(&rdev->sched_count) > 0)
goto exit; goto exit;
bnxt_re_ib_unreg(rdev, false); bnxt_re_ib_unreg(rdev, false);
bnxt_re_remove_one(rdev); bnxt_re_remove_one(rdev);
...@@ -1523,7 +1522,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier, ...@@ -1523,7 +1522,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
re_work->vlan_dev = (real_dev == netdev ? re_work->vlan_dev = (real_dev == netdev ?
NULL : netdev); NULL : netdev);
INIT_WORK(&re_work->work, bnxt_re_task); INIT_WORK(&re_work->work, bnxt_re_task);
set_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags); atomic_inc(&rdev->sched_count);
queue_work(bnxt_re_wq, &re_work->work); queue_work(bnxt_re_wq, &re_work->work);
} }
} }
......
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