diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 11:16:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 11:16:03 -0400 |
commit | 724bdd097e4d47b6ad963db5d92258ab5c485e05 (patch) | |
tree | f9d2de5f826780aa04532a89c3b67a01ae413f7d /drivers/net/mlx4/alloc.c | |
parent | dc8dcad83b53e3aebc52889e81772c00a1490408 (diff) | |
parent | 56f2fdaade2a6b91ccd785de938b91172d5c94f2 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
IB/ehca: Reject dynamic memory add/remove when ehca adapter is present
IB/ehca: Fix reported max number of QPs and CQs in systems with >1 adapter
IPoIB: Set netdev offload features properly for child (VLAN) interfaces
IPoIB: Clean up ethtool support
mlx4_core: Add Ethernet PCI device IDs
mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC
mlx4_core: Multiple port type support
mlx4_core: Ethernet MAC/VLAN management
mlx4_core: Get ethernet MTU and default address from firmware
mlx4_core: Support multiple pre-reserved QP regions
Update NetEffect maintainer emails to Intel emails
RDMA/cxgb3: Remove cmid reference on tid allocation failures
IB/mad: Use krealloc() to resize snoop table
IPoIB: Always initialize poll_timer to avoid crash on unload
IB/ehca: Don't allow creating UC QP with SRQ
mlx4_core: Add QP range reservation support
RDMA/ucma: Test ucma_alloc_multicast() return against NULL, not with IS_ERR()
Diffstat (limited to 'drivers/net/mlx4/alloc.c')
-rw-r--r-- | drivers/net/mlx4/alloc.c | 97 |
1 files changed, 88 insertions, 9 deletions
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index b411b79d72a..ad95d5f7b63 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c | |||
@@ -48,13 +48,16 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) | |||
48 | 48 | ||
49 | obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); | 49 | obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last); |
50 | if (obj >= bitmap->max) { | 50 | if (obj >= bitmap->max) { |
51 | bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; | 51 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) |
52 | & bitmap->mask; | ||
52 | obj = find_first_zero_bit(bitmap->table, bitmap->max); | 53 | obj = find_first_zero_bit(bitmap->table, bitmap->max); |
53 | } | 54 | } |
54 | 55 | ||
55 | if (obj < bitmap->max) { | 56 | if (obj < bitmap->max) { |
56 | set_bit(obj, bitmap->table); | 57 | set_bit(obj, bitmap->table); |
57 | bitmap->last = (obj + 1) & (bitmap->max - 1); | 58 | bitmap->last = (obj + 1); |
59 | if (bitmap->last == bitmap->max) | ||
60 | bitmap->last = 0; | ||
58 | obj |= bitmap->top; | 61 | obj |= bitmap->top; |
59 | } else | 62 | } else |
60 | obj = -1; | 63 | obj = -1; |
@@ -66,16 +69,90 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) | |||
66 | 69 | ||
67 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) | 70 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) |
68 | { | 71 | { |
69 | obj &= bitmap->max - 1; | 72 | mlx4_bitmap_free_range(bitmap, obj, 1); |
73 | } | ||
74 | |||
75 | static unsigned long find_aligned_range(unsigned long *bitmap, | ||
76 | u32 start, u32 nbits, | ||
77 | int len, int align) | ||
78 | { | ||
79 | unsigned long end, i; | ||
80 | |||
81 | again: | ||
82 | start = ALIGN(start, align); | ||
83 | |||
84 | while ((start < nbits) && test_bit(start, bitmap)) | ||
85 | start += align; | ||
86 | |||
87 | if (start >= nbits) | ||
88 | return -1; | ||
89 | |||
90 | end = start+len; | ||
91 | if (end > nbits) | ||
92 | return -1; | ||
93 | |||
94 | for (i = start + 1; i < end; i++) { | ||
95 | if (test_bit(i, bitmap)) { | ||
96 | start = i + 1; | ||
97 | goto again; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | return start; | ||
102 | } | ||
103 | |||
104 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) | ||
105 | { | ||
106 | u32 obj, i; | ||
107 | |||
108 | if (likely(cnt == 1 && align == 1)) | ||
109 | return mlx4_bitmap_alloc(bitmap); | ||
110 | |||
111 | spin_lock(&bitmap->lock); | ||
112 | |||
113 | obj = find_aligned_range(bitmap->table, bitmap->last, | ||
114 | bitmap->max, cnt, align); | ||
115 | if (obj >= bitmap->max) { | ||
116 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) | ||
117 | & bitmap->mask; | ||
118 | obj = find_aligned_range(bitmap->table, 0, bitmap->max, | ||
119 | cnt, align); | ||
120 | } | ||
121 | |||
122 | if (obj < bitmap->max) { | ||
123 | for (i = 0; i < cnt; i++) | ||
124 | set_bit(obj + i, bitmap->table); | ||
125 | if (obj == bitmap->last) { | ||
126 | bitmap->last = (obj + cnt); | ||
127 | if (bitmap->last >= bitmap->max) | ||
128 | bitmap->last = 0; | ||
129 | } | ||
130 | obj |= bitmap->top; | ||
131 | } else | ||
132 | obj = -1; | ||
133 | |||
134 | spin_unlock(&bitmap->lock); | ||
135 | |||
136 | return obj; | ||
137 | } | ||
138 | |||
139 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) | ||
140 | { | ||
141 | u32 i; | ||
142 | |||
143 | obj &= bitmap->max + bitmap->reserved_top - 1; | ||
70 | 144 | ||
71 | spin_lock(&bitmap->lock); | 145 | spin_lock(&bitmap->lock); |
72 | clear_bit(obj, bitmap->table); | 146 | for (i = 0; i < cnt; i++) |
147 | clear_bit(obj + i, bitmap->table); | ||
73 | bitmap->last = min(bitmap->last, obj); | 148 | bitmap->last = min(bitmap->last, obj); |
74 | bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; | 149 | bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top) |
150 | & bitmap->mask; | ||
75 | spin_unlock(&bitmap->lock); | 151 | spin_unlock(&bitmap->lock); |
76 | } | 152 | } |
77 | 153 | ||
78 | int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved) | 154 | int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, |
155 | u32 reserved_bot, u32 reserved_top) | ||
79 | { | 156 | { |
80 | int i; | 157 | int i; |
81 | 158 | ||
@@ -85,14 +162,16 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved | |||
85 | 162 | ||
86 | bitmap->last = 0; | 163 | bitmap->last = 0; |
87 | bitmap->top = 0; | 164 | bitmap->top = 0; |
88 | bitmap->max = num; | 165 | bitmap->max = num - reserved_top; |
89 | bitmap->mask = mask; | 166 | bitmap->mask = mask; |
167 | bitmap->reserved_top = reserved_top; | ||
90 | spin_lock_init(&bitmap->lock); | 168 | spin_lock_init(&bitmap->lock); |
91 | bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL); | 169 | bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) * |
170 | sizeof (long), GFP_KERNEL); | ||
92 | if (!bitmap->table) | 171 | if (!bitmap->table) |
93 | return -ENOMEM; | 172 | return -ENOMEM; |
94 | 173 | ||
95 | for (i = 0; i < reserved; ++i) | 174 | for (i = 0; i < reserved_bot; ++i) |
96 | set_bit(i, bitmap->table); | 175 | set_bit(i, bitmap->table); |
97 | 176 | ||
98 | return 0; | 177 | return 0; |