diff options
author | Stefani Seibold <stefani@seibold.net> | 2009-12-21 17:37:26 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-22 17:17:55 -0500 |
commit | 45465487897a1c6d508b14b904dc5777f7ec7e04 (patch) | |
tree | 935c8dae68dc793ff2f795d57cf027531475cd53 /drivers/infiniband | |
parent | 2ec91eec47f713e3d158ba5b28a24a85a2cf3650 (diff) |
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains. Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
- The API is to simple, important functions are missing
- A fifo can be only allocated dynamically
- There is a requirement of a spinlock whether you need it or not
- There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much. The new API has the following benefits:
- Generic usage: For kernel internal use and/or device driver.
- Provide an API for the most use case.
- Slim API: The whole API provides 25 functions.
- Linux style habit.
- DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
- Direct copy_to_user from the fifo and copy_from_user into the fifo.
- The kfifo itself is an in place member of the using data structure, this save an
indirection access and does not waste the kernel allocator.
- Lockless access: if only one reader and one writer is active on the fifo,
which is the common use case, no additional locking is necessary.
- Remove spinlock - give the user the freedom of choice what kind of locking to use if
one is required.
- Ability to handle records. Three type of records are supported:
- Variable length records between 0-255 bytes, with a record size
field of 1 bytes.
- Variable length records between 0-65535 bytes, with a record size
field of 2 bytes.
- Fixed size records, which no record size field.
- Preserve memory resource.
- Performance!
- Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure. This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them. This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/cxgb3/cxio_hal.h | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb3/cxio_resource.c | 60 |
2 files changed, 34 insertions, 35 deletions
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index bfd03bf8be54..f3d440cc68f2 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/kfifo.h> | ||
37 | 38 | ||
38 | #include "t3_cpl.h" | 39 | #include "t3_cpl.h" |
39 | #include "t3cdev.h" | 40 | #include "t3cdev.h" |
@@ -75,13 +76,13 @@ struct cxio_hal_ctrl_qp { | |||
75 | }; | 76 | }; |
76 | 77 | ||
77 | struct cxio_hal_resource { | 78 | struct cxio_hal_resource { |
78 | struct kfifo *tpt_fifo; | 79 | struct kfifo tpt_fifo; |
79 | spinlock_t tpt_fifo_lock; | 80 | spinlock_t tpt_fifo_lock; |
80 | struct kfifo *qpid_fifo; | 81 | struct kfifo qpid_fifo; |
81 | spinlock_t qpid_fifo_lock; | 82 | spinlock_t qpid_fifo_lock; |
82 | struct kfifo *cqid_fifo; | 83 | struct kfifo cqid_fifo; |
83 | spinlock_t cqid_fifo_lock; | 84 | spinlock_t cqid_fifo_lock; |
84 | struct kfifo *pdid_fifo; | 85 | struct kfifo pdid_fifo; |
85 | spinlock_t pdid_fifo_lock; | 86 | spinlock_t pdid_fifo_lock; |
86 | }; | 87 | }; |
87 | 88 | ||
diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index bd233c087653..65072bdfc1bf 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c | |||
@@ -39,12 +39,12 @@ | |||
39 | #include "cxio_resource.h" | 39 | #include "cxio_resource.h" |
40 | #include "cxio_hal.h" | 40 | #include "cxio_hal.h" |
41 | 41 | ||
42 | static struct kfifo *rhdl_fifo; | 42 | static struct kfifo rhdl_fifo; |
43 | static spinlock_t rhdl_fifo_lock; | 43 | static spinlock_t rhdl_fifo_lock; |
44 | 44 | ||
45 | #define RANDOM_SIZE 16 | 45 | #define RANDOM_SIZE 16 |
46 | 46 | ||
47 | static int __cxio_init_resource_fifo(struct kfifo **fifo, | 47 | static int __cxio_init_resource_fifo(struct kfifo *fifo, |
48 | spinlock_t *fifo_lock, | 48 | spinlock_t *fifo_lock, |
49 | u32 nr, u32 skip_low, | 49 | u32 nr, u32 skip_low, |
50 | u32 skip_high, | 50 | u32 skip_high, |
@@ -55,12 +55,11 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo, | |||
55 | u32 rarray[16]; | 55 | u32 rarray[16]; |
56 | spin_lock_init(fifo_lock); | 56 | spin_lock_init(fifo_lock); |
57 | 57 | ||
58 | *fifo = kfifo_alloc(nr * sizeof(u32), GFP_KERNEL, fifo_lock); | 58 | if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL, fifo_lock)) |
59 | if (IS_ERR(*fifo)) | ||
60 | return -ENOMEM; | 59 | return -ENOMEM; |
61 | 60 | ||
62 | for (i = 0; i < skip_low + skip_high; i++) | 61 | for (i = 0; i < skip_low + skip_high; i++) |
63 | __kfifo_put(*fifo, (unsigned char *) &entry, sizeof(u32)); | 62 | __kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)); |
64 | if (random) { | 63 | if (random) { |
65 | j = 0; | 64 | j = 0; |
66 | random_bytes = random32(); | 65 | random_bytes = random32(); |
@@ -72,33 +71,33 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo, | |||
72 | random_bytes = random32(); | 71 | random_bytes = random32(); |
73 | } | 72 | } |
74 | idx = (random_bytes >> (j * 2)) & 0xF; | 73 | idx = (random_bytes >> (j * 2)) & 0xF; |
75 | __kfifo_put(*fifo, | 74 | __kfifo_put(fifo, |
76 | (unsigned char *) &rarray[idx], | 75 | (unsigned char *) &rarray[idx], |
77 | sizeof(u32)); | 76 | sizeof(u32)); |
78 | rarray[idx] = i; | 77 | rarray[idx] = i; |
79 | j++; | 78 | j++; |
80 | } | 79 | } |
81 | for (i = 0; i < RANDOM_SIZE; i++) | 80 | for (i = 0; i < RANDOM_SIZE; i++) |
82 | __kfifo_put(*fifo, | 81 | __kfifo_put(fifo, |
83 | (unsigned char *) &rarray[i], | 82 | (unsigned char *) &rarray[i], |
84 | sizeof(u32)); | 83 | sizeof(u32)); |
85 | } else | 84 | } else |
86 | for (i = skip_low; i < nr - skip_high; i++) | 85 | for (i = skip_low; i < nr - skip_high; i++) |
87 | __kfifo_put(*fifo, (unsigned char *) &i, sizeof(u32)); | 86 | __kfifo_put(fifo, (unsigned char *) &i, sizeof(u32)); |
88 | 87 | ||
89 | for (i = 0; i < skip_low + skip_high; i++) | 88 | for (i = 0; i < skip_low + skip_high; i++) |
90 | kfifo_get(*fifo, (unsigned char *) &entry, sizeof(u32)); | 89 | kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)); |
91 | return 0; | 90 | return 0; |
92 | } | 91 | } |
93 | 92 | ||
94 | static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock, | 93 | static int cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock, |
95 | u32 nr, u32 skip_low, u32 skip_high) | 94 | u32 nr, u32 skip_low, u32 skip_high) |
96 | { | 95 | { |
97 | return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low, | 96 | return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low, |
98 | skip_high, 0)); | 97 | skip_high, 0)); |
99 | } | 98 | } |
100 | 99 | ||
101 | static int cxio_init_resource_fifo_random(struct kfifo **fifo, | 100 | static int cxio_init_resource_fifo_random(struct kfifo *fifo, |
102 | spinlock_t * fifo_lock, | 101 | spinlock_t * fifo_lock, |
103 | u32 nr, u32 skip_low, u32 skip_high) | 102 | u32 nr, u32 skip_low, u32 skip_high) |
104 | { | 103 | { |
@@ -113,15 +112,14 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) | |||
113 | 112 | ||
114 | spin_lock_init(&rdev_p->rscp->qpid_fifo_lock); | 113 | spin_lock_init(&rdev_p->rscp->qpid_fifo_lock); |
115 | 114 | ||
116 | rdev_p->rscp->qpid_fifo = kfifo_alloc(T3_MAX_NUM_QP * sizeof(u32), | 115 | if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32), |
117 | GFP_KERNEL, | 116 | GFP_KERNEL, |
118 | &rdev_p->rscp->qpid_fifo_lock); | 117 | &rdev_p->rscp->qpid_fifo_lock)) |
119 | if (IS_ERR(rdev_p->rscp->qpid_fifo)) | ||
120 | return -ENOMEM; | 118 | return -ENOMEM; |
121 | 119 | ||
122 | for (i = 16; i < T3_MAX_NUM_QP; i++) | 120 | for (i = 16; i < T3_MAX_NUM_QP; i++) |
123 | if (!(i & rdev_p->qpmask)) | 121 | if (!(i & rdev_p->qpmask)) |
124 | __kfifo_put(rdev_p->rscp->qpid_fifo, | 122 | __kfifo_put(&rdev_p->rscp->qpid_fifo, |
125 | (unsigned char *) &i, sizeof(u32)); | 123 | (unsigned char *) &i, sizeof(u32)); |
126 | return 0; | 124 | return 0; |
127 | } | 125 | } |
@@ -134,7 +132,7 @@ int cxio_hal_init_rhdl_resource(u32 nr_rhdl) | |||
134 | 132 | ||
135 | void cxio_hal_destroy_rhdl_resource(void) | 133 | void cxio_hal_destroy_rhdl_resource(void) |
136 | { | 134 | { |
137 | kfifo_free(rhdl_fifo); | 135 | kfifo_free(&rhdl_fifo); |
138 | } | 136 | } |
139 | 137 | ||
140 | /* nr_* must be power of 2 */ | 138 | /* nr_* must be power of 2 */ |
@@ -167,11 +165,11 @@ int cxio_hal_init_resource(struct cxio_rdev *rdev_p, | |||
167 | goto pdid_err; | 165 | goto pdid_err; |
168 | return 0; | 166 | return 0; |
169 | pdid_err: | 167 | pdid_err: |
170 | kfifo_free(rscp->cqid_fifo); | 168 | kfifo_free(&rscp->cqid_fifo); |
171 | cqid_err: | 169 | cqid_err: |
172 | kfifo_free(rscp->qpid_fifo); | 170 | kfifo_free(&rscp->qpid_fifo); |
173 | qpid_err: | 171 | qpid_err: |
174 | kfifo_free(rscp->tpt_fifo); | 172 | kfifo_free(&rscp->tpt_fifo); |
175 | tpt_err: | 173 | tpt_err: |
176 | return -ENOMEM; | 174 | return -ENOMEM; |
177 | } | 175 | } |
@@ -195,17 +193,17 @@ static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry) | |||
195 | 193 | ||
196 | u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) | 194 | u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) |
197 | { | 195 | { |
198 | return cxio_hal_get_resource(rscp->tpt_fifo); | 196 | return cxio_hal_get_resource(&rscp->tpt_fifo); |
199 | } | 197 | } |
200 | 198 | ||
201 | void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) | 199 | void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) |
202 | { | 200 | { |
203 | cxio_hal_put_resource(rscp->tpt_fifo, stag); | 201 | cxio_hal_put_resource(&rscp->tpt_fifo, stag); |
204 | } | 202 | } |
205 | 203 | ||
206 | u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) | 204 | u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) |
207 | { | 205 | { |
208 | u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo); | 206 | u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo); |
209 | PDBG("%s qpid 0x%x\n", __func__, qpid); | 207 | PDBG("%s qpid 0x%x\n", __func__, qpid); |
210 | return qpid; | 208 | return qpid; |
211 | } | 209 | } |
@@ -213,35 +211,35 @@ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) | |||
213 | void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) | 211 | void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) |
214 | { | 212 | { |
215 | PDBG("%s qpid 0x%x\n", __func__, qpid); | 213 | PDBG("%s qpid 0x%x\n", __func__, qpid); |
216 | cxio_hal_put_resource(rscp->qpid_fifo, qpid); | 214 | cxio_hal_put_resource(&rscp->qpid_fifo, qpid); |
217 | } | 215 | } |
218 | 216 | ||
219 | u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) | 217 | u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) |
220 | { | 218 | { |
221 | return cxio_hal_get_resource(rscp->cqid_fifo); | 219 | return cxio_hal_get_resource(&rscp->cqid_fifo); |
222 | } | 220 | } |
223 | 221 | ||
224 | void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) | 222 | void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) |
225 | { | 223 | { |
226 | cxio_hal_put_resource(rscp->cqid_fifo, cqid); | 224 | cxio_hal_put_resource(&rscp->cqid_fifo, cqid); |
227 | } | 225 | } |
228 | 226 | ||
229 | u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) | 227 | u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) |
230 | { | 228 | { |
231 | return cxio_hal_get_resource(rscp->pdid_fifo); | 229 | return cxio_hal_get_resource(&rscp->pdid_fifo); |
232 | } | 230 | } |
233 | 231 | ||
234 | void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) | 232 | void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) |
235 | { | 233 | { |
236 | cxio_hal_put_resource(rscp->pdid_fifo, pdid); | 234 | cxio_hal_put_resource(&rscp->pdid_fifo, pdid); |
237 | } | 235 | } |
238 | 236 | ||
239 | void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) | 237 | void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) |
240 | { | 238 | { |
241 | kfifo_free(rscp->tpt_fifo); | 239 | kfifo_free(&rscp->tpt_fifo); |
242 | kfifo_free(rscp->cqid_fifo); | 240 | kfifo_free(&rscp->cqid_fifo); |
243 | kfifo_free(rscp->qpid_fifo); | 241 | kfifo_free(&rscp->qpid_fifo); |
244 | kfifo_free(rscp->pdid_fifo); | 242 | kfifo_free(&rscp->pdid_fifo); |
245 | kfree(rscp); | 243 | kfree(rscp); |
246 | } | 244 | } |
247 | 245 | ||