diff options
Diffstat (limited to 'drivers/net/mlx4/alloc.c')
-rw-r--r-- | drivers/net/mlx4/alloc.c | 74 |
1 files changed, 73 insertions, 1 deletions
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c index 096bca54bcf7..e6c0d5bb5dcb 100644 --- a/drivers/net/mlx4/alloc.c +++ b/drivers/net/mlx4/alloc.c | |||
@@ -65,10 +65,82 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap) | |||
65 | 65 | ||
66 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) | 66 | void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) |
67 | { | 67 | { |
68 | mlx4_bitmap_free_range(bitmap, obj, 1); | ||
69 | } | ||
70 | |||
71 | static unsigned long find_aligned_range(unsigned long *bitmap, | ||
72 | u32 start, u32 nbits, | ||
73 | int len, int align) | ||
74 | { | ||
75 | unsigned long end, i; | ||
76 | |||
77 | again: | ||
78 | start = ALIGN(start, align); | ||
79 | |||
80 | while ((start < nbits) && test_bit(start, bitmap)) | ||
81 | start += align; | ||
82 | |||
83 | if (start >= nbits) | ||
84 | return -1; | ||
85 | |||
86 | end = start+len; | ||
87 | if (end > nbits) | ||
88 | return -1; | ||
89 | |||
90 | for (i = start + 1; i < end; i++) { | ||
91 | if (test_bit(i, bitmap)) { | ||
92 | start = i + 1; | ||
93 | goto again; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return start; | ||
98 | } | ||
99 | |||
100 | u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align) | ||
101 | { | ||
102 | u32 obj, i; | ||
103 | |||
104 | if (likely(cnt == 1 && align == 1)) | ||
105 | return mlx4_bitmap_alloc(bitmap); | ||
106 | |||
107 | spin_lock(&bitmap->lock); | ||
108 | |||
109 | obj = find_aligned_range(bitmap->table, bitmap->last, | ||
110 | bitmap->max, cnt, align); | ||
111 | if (obj >= bitmap->max) { | ||
112 | bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; | ||
113 | obj = find_aligned_range(bitmap->table, 0, | ||
114 | bitmap->max, | ||
115 | cnt, align); | ||
116 | } | ||
117 | |||
118 | if (obj < bitmap->max) { | ||
119 | for (i = 0; i < cnt; i++) | ||
120 | set_bit(obj + i, bitmap->table); | ||
121 | if (obj == bitmap->last) { | ||
122 | bitmap->last = (obj + cnt); | ||
123 | if (bitmap->last >= bitmap->max) | ||
124 | bitmap->last = 0; | ||
125 | } | ||
126 | obj |= bitmap->top; | ||
127 | } else | ||
128 | obj = -1; | ||
129 | |||
130 | spin_unlock(&bitmap->lock); | ||
131 | |||
132 | return obj; | ||
133 | } | ||
134 | |||
135 | void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt) | ||
136 | { | ||
137 | u32 i; | ||
138 | |||
68 | obj &= bitmap->max - 1; | 139 | obj &= bitmap->max - 1; |
69 | 140 | ||
70 | spin_lock(&bitmap->lock); | 141 | spin_lock(&bitmap->lock); |
71 | clear_bit(obj, bitmap->table); | 142 | for (i = 0; i < cnt; i++) |
143 | clear_bit(obj + i, bitmap->table); | ||
72 | bitmap->last = min(bitmap->last, obj); | 144 | bitmap->last = min(bitmap->last, obj); |
73 | bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; | 145 | bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; |
74 | spin_unlock(&bitmap->lock); | 146 | spin_unlock(&bitmap->lock); |