Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -120,7 +120,6 @@ struct bnxt_re_dev {
#define BNXT_RE_FLAG_HAVE_L2_REF		3
#define BNXT_RE_FLAG_RCFW_CHANNEL_EN		4
#define BNXT_RE_FLAG_QOS_WORK_REG		5
#define BNXT_RE_FLAG_TASK_IN_PROG		6
#define BNXT_RE_FLAG_ISSUE_ROCE_STATS          29
	struct net_device		*netdev;
	unsigned int			version, major, minor;
@@ -158,6 +157,7 @@ struct bnxt_re_dev {
	atomic_t			srq_count;
	atomic_t			mr_count;
	atomic_t			mw_count;
	atomic_t			sched_count;
	/* Max of 2 lossless traffic class supported per port */
	u16				cosq[2];

+3 −4
Original line number Diff line number Diff line
@@ -656,7 +656,6 @@ static void bnxt_re_dev_remove(struct bnxt_re_dev *rdev)
	mutex_unlock(&bnxt_re_dev_lock);

	synchronize_rcu();
	flush_workqueue(bnxt_re_wq);

	ib_dealloc_device(&rdev->ibdev);
	/* rdev is gone */
@@ -1441,7 +1440,7 @@ static void bnxt_re_task(struct work_struct *work)
		break;
	}
	smp_mb__before_atomic();
	clear_bit(BNXT_RE_FLAG_TASK_IN_PROG, &rdev->flags);
	atomic_dec(&rdev->sched_count);
	kfree(re_work);
}

@@ -1503,7 +1502,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
		/* netdev notifier will call NETDEV_UNREGISTER again later since
		 * 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;
		bnxt_re_ib_unreg(rdev, false);
		bnxt_re_remove_one(rdev);
@@ -1523,7 +1522,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
			re_work->vlan_dev = (real_dev == netdev ?
					     NULL : netdev);
			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);
		}
	}