]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
SDP - Fix reference count locking bug
authorJim Mott <jim@mellanox.com>
Tue, 6 Nov 2007 22:28:05 +0000 (14:28 -0800)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 6 Oct 2015 12:04:11 +0000 (05:04 -0700)
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 <jim@mellanox.com>
drivers/infiniband/ulp/sdp/sdp_main.c

index d1eb6ab6b37cbbe68b148e7518397e1aa27d1bc8..84c3ff4679e69cce997b2e2d88ce9c8721bd60c5 100644 (file)
@@ -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);