aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorStefani Seibold <stefani@seibold.net>2009-12-21 17:37:26 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-22 17:17:55 -0500
commit45465487897a1c6d508b14b904dc5777f7ec7e04 (patch)
tree935c8dae68dc793ff2f795d57cf027531475cd53 /drivers/infiniband
parent2ec91eec47f713e3d158ba5b28a24a85a2cf3650 (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.h9
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_resource.c60
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
77struct cxio_hal_resource { 78struct 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
42static struct kfifo *rhdl_fifo; 42static struct kfifo rhdl_fifo;
43static spinlock_t rhdl_fifo_lock; 43static spinlock_t rhdl_fifo_lock;
44 44
45#define RANDOM_SIZE 16 45#define RANDOM_SIZE 16
46 46
47static int __cxio_init_resource_fifo(struct kfifo **fifo, 47static 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
94static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock, 93static 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
101static int cxio_init_resource_fifo_random(struct kfifo **fifo, 100static 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
135void cxio_hal_destroy_rhdl_resource(void) 133void 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;
169pdid_err: 167pdid_err:
170 kfifo_free(rscp->cqid_fifo); 168 kfifo_free(&rscp->cqid_fifo);
171cqid_err: 169cqid_err:
172 kfifo_free(rscp->qpid_fifo); 170 kfifo_free(&rscp->qpid_fifo);
173qpid_err: 171qpid_err:
174 kfifo_free(rscp->tpt_fifo); 172 kfifo_free(&rscp->tpt_fifo);
175tpt_err: 173tpt_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
196u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) 194u32 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
201void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) 199void 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
206u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) 204u32 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)
213void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) 211void 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
219u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) 217u32 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
224void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) 222void 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
229u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) 227u32 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
234void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) 232void 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
239void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) 237void 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