[PATCH v7 3/5] rdma_rxe: schedule ib_unregister_device_and_put()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Schedule ib_unregister_device_and_put() to run in a workqueue context
to avoid a deadlock when processing NETDEV_UNREGISTER events.

Signed-off-by: Steve Wise <swise@xxxxxxxxxxxxxxxxxxxxx>
---
 drivers/infiniband/sw/rxe/rxe.c       |  1 +
 drivers/infiniband/sw/rxe/rxe_net.c   | 10 +++++++++-
 drivers/infiniband/sw/rxe/rxe_net.h   |  1 +
 drivers/infiniband/sw/rxe/rxe_verbs.h |  1 +
 4 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
index 4069463f9a66..91ad339fd6e1 100644
--- a/drivers/infiniband/sw/rxe/rxe.c
+++ b/drivers/infiniband/sw/rxe/rxe.c
@@ -272,6 +272,7 @@ static int rxe_init(struct rxe_dev *rxe)
 	spin_lock_init(&rxe->mmap_offset_lock);
 	spin_lock_init(&rxe->pending_lock);
 	INIT_LIST_HEAD(&rxe->pending_mmaps);
+	INIT_WORK(&rxe->netdev_unregister_work, rxe_netdev_unregister_work);
 
 	mutex_init(&rxe->usdev_lock);
 
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 6a25b514d448..c05549d09268 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -585,6 +585,14 @@ void rxe_set_port_state(struct net_device *ndev, struct rxe_dev *rxe)
 		rxe_port_down(rxe);
 }
 
+void rxe_netdev_unregister_work(struct work_struct *work)
+{
+	struct rxe_dev *rxe;
+
+	rxe = container_of(work, struct rxe_dev, netdev_unregister_work);
+	ib_unregister_device_and_put(&rxe->ib_dev);
+}
+
 static int rxe_notify(struct notifier_block *not_blk,
 		      unsigned long event,
 		      void *arg)
@@ -597,7 +605,7 @@ static int rxe_notify(struct notifier_block *not_blk,
 
 	switch (event) {
 	case NETDEV_UNREGISTER:
-		ib_unregister_device_and_put(&rxe->ib_dev);
+		schedule_work(&rxe->netdev_unregister_work);
 		return NOTIFY_OK;
 
 	case NETDEV_UP:
diff --git a/drivers/infiniband/sw/rxe/rxe_net.h b/drivers/infiniband/sw/rxe/rxe_net.h
index 106c586dbb26..685aa98baf55 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.h
+++ b/drivers/infiniband/sw/rxe/rxe_net.h
@@ -47,5 +47,6 @@ struct rxe_recv_sockets {
 
 int rxe_net_init(void);
 void rxe_net_exit(void);
+void rxe_netdev_unregister_work(struct work_struct *work);
 
 #endif /* RXE_NET_H */
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index a0b635812784..ce63cbf0d738 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -412,6 +412,7 @@ struct rxe_dev {
 
 	struct rxe_port		port;
 	struct crypto_shash	*tfm;
+	struct work_struct	netdev_unregister_work;
 };
 
 static inline void rxe_counter_inc(struct rxe_dev *rxe, enum rxe_counters cnt)
-- 
1.8.3.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux