Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/mthca: Use IRQ safe locks to protect allocation bitmaps

It is supposed to be OK to call mthca_create_ah() and mthca_destroy_ah()
from any context. However, for mem-full HCAs, these functions use the
mthca_alloc() and mthca_free() bitmap helpers, and those helpers use
non-IRQ-safe spin_lock() internally. Lockdep correctly warns that
this could lead to a deadlock. Fix this by changing mthca_alloc() and
mthca_free() to use spin_lock_irqsave().

Signed-off-by: Roland Dreier <rolandd@cisco.com>

+11 -4
+11 -4
drivers/infiniband/hw/mthca/mthca_allocator.c
··· 41 41 /* Trivial bitmap-based allocator */ 42 42 u32 mthca_alloc(struct mthca_alloc *alloc) 43 43 { 44 + unsigned long flags; 44 45 u32 obj; 45 46 46 - spin_lock(&alloc->lock); 47 + spin_lock_irqsave(&alloc->lock, flags); 48 + 47 49 obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last); 48 50 if (obj >= alloc->max) { 49 51 alloc->top = (alloc->top + alloc->max) & alloc->mask; ··· 58 56 } else 59 57 obj = -1; 60 58 61 - spin_unlock(&alloc->lock); 59 + spin_unlock_irqrestore(&alloc->lock, flags); 62 60 63 61 return obj; 64 62 } 65 63 66 64 void mthca_free(struct mthca_alloc *alloc, u32 obj) 67 65 { 66 + unsigned long flags; 67 + 68 68 obj &= alloc->max - 1; 69 - spin_lock(&alloc->lock); 69 + 70 + spin_lock_irqsave(&alloc->lock, flags); 71 + 70 72 clear_bit(obj, alloc->table); 71 73 alloc->last = min(alloc->last, obj); 72 74 alloc->top = (alloc->top + alloc->max) & alloc->mask; 73 - spin_unlock(&alloc->lock); 75 + 76 + spin_unlock_irqrestore(&alloc->lock, flags); 74 77 } 75 78 76 79 int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask,