1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/kernel.h>
33#include <linux/random.h>
34#include "iw_cxgb4.h"
35
36#define RANDOM_SKIP 16
37
38
39
40
41
42
43
44u32 c4iw_id_alloc(struct c4iw_id_table *alloc)
45{
46 unsigned long flags;
47 u32 obj;
48
49 spin_lock_irqsave(&alloc->lock, flags);
50
51 obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last);
52 if (obj >= alloc->max)
53 obj = find_first_zero_bit(alloc->table, alloc->max);
54
55 if (obj < alloc->max) {
56 if (alloc->flags & C4IW_ID_TABLE_F_RANDOM)
57 alloc->last += prandom_u32() % RANDOM_SKIP;
58 else
59 alloc->last = obj + 1;
60 if (alloc->last >= alloc->max)
61 alloc->last = 0;
62 set_bit(obj, alloc->table);
63 obj += alloc->start;
64 } else
65 obj = -1;
66
67 spin_unlock_irqrestore(&alloc->lock, flags);
68 return obj;
69}
70
71void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj)
72{
73 unsigned long flags;
74
75 obj -= alloc->start;
76 BUG_ON((int)obj < 0);
77
78 spin_lock_irqsave(&alloc->lock, flags);
79 clear_bit(obj, alloc->table);
80 spin_unlock_irqrestore(&alloc->lock, flags);
81}
82
83int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
84 u32 reserved, u32 flags)
85{
86 int i;
87
88 alloc->start = start;
89 alloc->flags = flags;
90 if (flags & C4IW_ID_TABLE_F_RANDOM)
91 alloc->last = prandom_u32() % RANDOM_SKIP;
92 else
93 alloc->last = 0;
94 alloc->max = num;
95 spin_lock_init(&alloc->lock);
96 alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof(long),
97 GFP_KERNEL);
98 if (!alloc->table)
99 return -ENOMEM;
100
101 bitmap_zero(alloc->table, num);
102 if (!(alloc->flags & C4IW_ID_TABLE_F_EMPTY))
103 for (i = 0; i < reserved; ++i)
104 set_bit(i, alloc->table);
105
106 return 0;
107}
108
109void c4iw_id_table_free(struct c4iw_id_table *alloc)
110{
111 kfree(alloc->table);
112}
113