From 6c52b57f5ec1d510b89231ebc55acbe010957967 Mon Sep 17 00:00:00 2001 From: Jim Mott Date: Tue, 6 Nov 2007 14:28:05 -0800 Subject: [PATCH] SDP - Fix reference count locking bug Add code to fix a problem found by the Mellanox regression group. When mlx4_ib driver is unloaded while SDP connections are active, the system would hang. The original fix for this problem called an rdma_cm service that can block with 2 spin locks held. Signed-off-by: Jim Mott --- drivers/infiniband/ulp/sdp/sdp_main.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/ulp/sdp/sdp_main.c b/drivers/infiniband/ulp/sdp/sdp_main.c index d1eb6ab6b37c..84c3ff4679e6 100644 --- a/drivers/infiniband/ulp/sdp/sdp_main.c +++ b/drivers/infiniband/ulp/sdp/sdp_main.c @@ -2234,10 +2234,12 @@ static void sdp_add_device(struct ib_device *device) static void sdp_remove_device(struct ib_device *device) { - struct list_head *p; - struct sdp_sock *ssk; - struct sock *sk; + struct list_head *p; + struct sdp_sock *ssk; + struct sock *sk; + struct rdma_cm_id *id; +do_next: write_lock(&device_removal_lock); spin_lock_irq(&sock_list_lock); @@ -2245,16 +2247,30 @@ static void sdp_remove_device(struct ib_device *device) ssk = list_entry(p, struct sdp_sock, sock_list); if (ssk->ib_device == device) { sk = &ssk->isk.sk; + id = ssk->id; - if (ssk->id) { - rdma_destroy_id(ssk->id); + if (id) { ssk->id = NULL; + + spin_unlock_irq(&sock_list_lock); + write_unlock(&device_removal_lock); + rdma_destroy_id(id); + + goto do_next; } + } + } + + list_for_each(p, &sock_list) { + ssk = list_entry(p, struct sdp_sock, sock_list); + if (ssk->ib_device == device) { + sk = &ssk->isk.sk; sk->sk_shutdown |= RCV_SHUTDOWN; sdp_reset(sk); } } + spin_unlock_irq(&sock_list_lock); write_unlock(&device_removal_lock); -- 2.50.1