aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/mlx4/alloc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 11:16:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 11:16:03 -0400
commit724bdd097e4d47b6ad963db5d92258ab5c485e05 (patch)
treef9d2de5f826780aa04532a89c3b67a01ae413f7d /drivers/net/mlx4/alloc.c
parentdc8dcad83b53e3aebc52889e81772c00a1490408 (diff)
parent56f2fdaade2a6b91ccd785de938b91172d5c94f2 (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.c97
1 files changed, 88 insertions, 9 deletions
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index b411b79d72ad..ad95d5f7b630 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
67void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) 70void 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
75static 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
81again:
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
104u32 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
139void 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
78int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved) 154int 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;