aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb4/resource.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/cxgb4/resource.c')
-rw-r--r--drivers/infiniband/hw/cxgb4/resource.c180
1 files changed, 74 insertions, 106 deletions
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 407ff3924150..cdef4d7fb6d8 100644
--- a/drivers/infiniband/hw/cxgb4/resource.c
+++ b/drivers/infiniband/hw/cxgb4/resource.c
@@ -30,96 +30,25 @@
30 * SOFTWARE. 30 * SOFTWARE.
31 */ 31 */
32/* Crude resource management */ 32/* Crude resource management */
33#include <linux/kernel.h>
34#include <linux/random.h>
35#include <linux/slab.h>
36#include <linux/kfifo.h>
37#include <linux/spinlock.h> 33#include <linux/spinlock.h>
38#include <linux/errno.h>
39#include <linux/genalloc.h> 34#include <linux/genalloc.h>
40#include <linux/ratelimit.h> 35#include <linux/ratelimit.h>
41#include "iw_cxgb4.h" 36#include "iw_cxgb4.h"
42 37
43#define RANDOM_SIZE 16 38static int c4iw_init_qid_table(struct c4iw_rdev *rdev)
44
45static int __c4iw_init_resource_fifo(struct kfifo *fifo,
46 spinlock_t *fifo_lock,
47 u32 nr, u32 skip_low,
48 u32 skip_high,
49 int random)
50{
51 u32 i, j, entry = 0, idx;
52 u32 random_bytes;
53 u32 rarray[16];
54 spin_lock_init(fifo_lock);
55
56 if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL))
57 return -ENOMEM;
58
59 for (i = 0; i < skip_low + skip_high; i++)
60 kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
61 if (random) {
62 j = 0;
63 random_bytes = random32();
64 for (i = 0; i < RANDOM_SIZE; i++)
65 rarray[i] = i + skip_low;
66 for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
67 if (j >= RANDOM_SIZE) {
68 j = 0;
69 random_bytes = random32();
70 }
71 idx = (random_bytes >> (j * 2)) & 0xF;
72 kfifo_in(fifo,
73 (unsigned char *) &rarray[idx],
74 sizeof(u32));
75 rarray[idx] = i;
76 j++;
77 }
78 for (i = 0; i < RANDOM_SIZE; i++)
79 kfifo_in(fifo,
80 (unsigned char *) &rarray[i],
81 sizeof(u32));
82 } else
83 for (i = skip_low; i < nr - skip_high; i++)
84 kfifo_in(fifo, (unsigned char *) &i, sizeof(u32));
85
86 for (i = 0; i < skip_low + skip_high; i++)
87 if (kfifo_out_locked(fifo, (unsigned char *) &entry,
88 sizeof(u32), fifo_lock))
89 break;
90 return 0;
91}
92
93static int c4iw_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock,
94 u32 nr, u32 skip_low, u32 skip_high)
95{
96 return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
97 skip_high, 0);
98}
99
100static int c4iw_init_resource_fifo_random(struct kfifo *fifo,
101 spinlock_t *fifo_lock,
102 u32 nr, u32 skip_low, u32 skip_high)
103{
104 return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
105 skip_high, 1);
106}
107
108static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
109{ 39{
110 u32 i; 40 u32 i;
111 41
112 spin_lock_init(&rdev->resource.qid_fifo_lock); 42 if (c4iw_id_table_alloc(&rdev->resource.qid_table,
113 43 rdev->lldi.vr->qp.start,
114 if (kfifo_alloc(&rdev->resource.qid_fifo, rdev->lldi.vr->qp.size * 44 rdev->lldi.vr->qp.size,
115 sizeof(u32), GFP_KERNEL)) 45 rdev->lldi.vr->qp.size, 0))
116 return -ENOMEM; 46 return -ENOMEM;
117 47
118 for (i = rdev->lldi.vr->qp.start; 48 for (i = rdev->lldi.vr->qp.start;
119 i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++) 49 i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
120 if (!(i & rdev->qpmask)) 50 if (!(i & rdev->qpmask))
121 kfifo_in(&rdev->resource.qid_fifo, 51 c4iw_id_free(&rdev->resource.qid_table, i);
122 (unsigned char *) &i, sizeof(u32));
123 return 0; 52 return 0;
124} 53}
125 54
@@ -127,44 +56,42 @@ static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
127int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid) 56int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid)
128{ 57{
129 int err = 0; 58 int err = 0;
130 err = c4iw_init_resource_fifo_random(&rdev->resource.tpt_fifo, 59 err = c4iw_id_table_alloc(&rdev->resource.tpt_table, 0, nr_tpt, 1,
131 &rdev->resource.tpt_fifo_lock, 60 C4IW_ID_TABLE_F_RANDOM);
132 nr_tpt, 1, 0);
133 if (err) 61 if (err)
134 goto tpt_err; 62 goto tpt_err;
135 err = c4iw_init_qid_fifo(rdev); 63 err = c4iw_init_qid_table(rdev);
136 if (err) 64 if (err)
137 goto qid_err; 65 goto qid_err;
138 err = c4iw_init_resource_fifo(&rdev->resource.pdid_fifo, 66 err = c4iw_id_table_alloc(&rdev->resource.pdid_table, 0,
139 &rdev->resource.pdid_fifo_lock, 67 nr_pdid, 1, 0);
140 nr_pdid, 1, 0);
141 if (err) 68 if (err)
142 goto pdid_err; 69 goto pdid_err;
143 return 0; 70 return 0;
144pdid_err: 71 pdid_err:
145 kfifo_free(&rdev->resource.qid_fifo); 72 c4iw_id_table_free(&rdev->resource.qid_table);
146qid_err: 73 qid_err:
147 kfifo_free(&rdev->resource.tpt_fifo); 74 c4iw_id_table_free(&rdev->resource.tpt_table);
148tpt_err: 75 tpt_err:
149 return -ENOMEM; 76 return -ENOMEM;
150} 77}
151 78
152/* 79/*
153 * returns 0 if no resource available 80 * returns 0 if no resource available
154 */ 81 */
155u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock) 82u32 c4iw_get_resource(struct c4iw_id_table *id_table)
156{ 83{
157 u32 entry; 84 u32 entry;
158 if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)) 85 entry = c4iw_id_alloc(id_table);
159 return entry; 86 if (entry == (u32)(-1))
160 else
161 return 0; 87 return 0;
88 return entry;
162} 89}
163 90
164void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock) 91void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry)
165{ 92{
166 PDBG("%s entry 0x%x\n", __func__, entry); 93 PDBG("%s entry 0x%x\n", __func__, entry);
167 kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock); 94 c4iw_id_free(id_table, entry);
168} 95}
169 96
170u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx) 97u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
@@ -181,10 +108,12 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
181 qid = entry->qid; 108 qid = entry->qid;
182 kfree(entry); 109 kfree(entry);
183 } else { 110 } else {
184 qid = c4iw_get_resource(&rdev->resource.qid_fifo, 111 qid = c4iw_get_resource(&rdev->resource.qid_table);
185 &rdev->resource.qid_fifo_lock);
186 if (!qid) 112 if (!qid)
187 goto out; 113 goto out;
114 mutex_lock(&rdev->stats.lock);
115 rdev->stats.qid.cur += rdev->qpmask + 1;
116 mutex_unlock(&rdev->stats.lock);
188 for (i = qid+1; i & rdev->qpmask; i++) { 117 for (i = qid+1; i & rdev->qpmask; i++) {
189 entry = kmalloc(sizeof *entry, GFP_KERNEL); 118 entry = kmalloc(sizeof *entry, GFP_KERNEL);
190 if (!entry) 119 if (!entry)
@@ -213,6 +142,10 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
213out: 142out:
214 mutex_unlock(&uctx->lock); 143 mutex_unlock(&uctx->lock);
215 PDBG("%s qid 0x%x\n", __func__, qid); 144 PDBG("%s qid 0x%x\n", __func__, qid);
145 mutex_lock(&rdev->stats.lock);
146 if (rdev->stats.qid.cur > rdev->stats.qid.max)
147 rdev->stats.qid.max = rdev->stats.qid.cur;
148 mutex_unlock(&rdev->stats.lock);
216 return qid; 149 return qid;
217} 150}
218 151
@@ -245,10 +178,12 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
245 qid = entry->qid; 178 qid = entry->qid;
246 kfree(entry); 179 kfree(entry);
247 } else { 180 } else {
248 qid = c4iw_get_resource(&rdev->resource.qid_fifo, 181 qid = c4iw_get_resource(&rdev->resource.qid_table);
249 &rdev->resource.qid_fifo_lock);
250 if (!qid) 182 if (!qid)
251 goto out; 183 goto out;
184 mutex_lock(&rdev->stats.lock);
185 rdev->stats.qid.cur += rdev->qpmask + 1;
186 mutex_unlock(&rdev->stats.lock);
252 for (i = qid+1; i & rdev->qpmask; i++) { 187 for (i = qid+1; i & rdev->qpmask; i++) {
253 entry = kmalloc(sizeof *entry, GFP_KERNEL); 188 entry = kmalloc(sizeof *entry, GFP_KERNEL);
254 if (!entry) 189 if (!entry)
@@ -277,6 +212,10 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
277out: 212out:
278 mutex_unlock(&uctx->lock); 213 mutex_unlock(&uctx->lock);
279 PDBG("%s qid 0x%x\n", __func__, qid); 214 PDBG("%s qid 0x%x\n", __func__, qid);
215 mutex_lock(&rdev->stats.lock);
216 if (rdev->stats.qid.cur > rdev->stats.qid.max)
217 rdev->stats.qid.max = rdev->stats.qid.cur;
218 mutex_unlock(&rdev->stats.lock);
280 return qid; 219 return qid;
281} 220}
282 221
@@ -297,9 +236,9 @@ void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qid,
297 236
298void c4iw_destroy_resource(struct c4iw_resource *rscp) 237void c4iw_destroy_resource(struct c4iw_resource *rscp)
299{ 238{
300 kfifo_free(&rscp->tpt_fifo); 239 c4iw_id_table_free(&rscp->tpt_table);
301 kfifo_free(&rscp->qid_fifo); 240 c4iw_id_table_free(&rscp->qid_table);
302 kfifo_free(&rscp->pdid_fifo); 241 c4iw_id_table_free(&rscp->pdid_table);
303} 242}
304 243
305/* 244/*
@@ -312,15 +251,23 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
312{ 251{
313 unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size); 252 unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
314 PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size); 253 PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
315 if (!addr) 254 mutex_lock(&rdev->stats.lock);
316 printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n", 255 if (addr) {
317 pci_name(rdev->lldi.pdev)); 256 rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
257 if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
258 rdev->stats.pbl.max = rdev->stats.pbl.cur;
259 } else
260 rdev->stats.pbl.fail++;
261 mutex_unlock(&rdev->stats.lock);
318 return (u32)addr; 262 return (u32)addr;
319} 263}
320 264
321void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size) 265void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size)
322{ 266{
323 PDBG("%s addr 0x%x size %d\n", __func__, addr, size); 267 PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
268 mutex_lock(&rdev->stats.lock);
269 rdev->stats.pbl.cur -= roundup(size, 1 << MIN_PBL_SHIFT);
270 mutex_unlock(&rdev->stats.lock);
324 gen_pool_free(rdev->pbl_pool, (unsigned long)addr, size); 271 gen_pool_free(rdev->pbl_pool, (unsigned long)addr, size);
325} 272}
326 273
@@ -377,12 +324,23 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
377 if (!addr) 324 if (!addr)
378 printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n", 325 printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
379 pci_name(rdev->lldi.pdev)); 326 pci_name(rdev->lldi.pdev));
327 mutex_lock(&rdev->stats.lock);
328 if (addr) {
329 rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
330 if (rdev->stats.rqt.cur > rdev->stats.rqt.max)
331 rdev->stats.rqt.max = rdev->stats.rqt.cur;
332 } else
333 rdev->stats.rqt.fail++;
334 mutex_unlock(&rdev->stats.lock);
380 return (u32)addr; 335 return (u32)addr;
381} 336}
382 337
383void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size) 338void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size)
384{ 339{
385 PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6); 340 PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6);
341 mutex_lock(&rdev->stats.lock);
342 rdev->stats.rqt.cur -= roundup(size << 6, 1 << MIN_RQT_SHIFT);
343 mutex_unlock(&rdev->stats.lock);
386 gen_pool_free(rdev->rqt_pool, (unsigned long)addr, size << 6); 344 gen_pool_free(rdev->rqt_pool, (unsigned long)addr, size << 6);
387} 345}
388 346
@@ -433,12 +391,22 @@ u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size)
433{ 391{
434 unsigned long addr = gen_pool_alloc(rdev->ocqp_pool, size); 392 unsigned long addr = gen_pool_alloc(rdev->ocqp_pool, size);
435 PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size); 393 PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
394 if (addr) {
395 mutex_lock(&rdev->stats.lock);
396 rdev->stats.ocqp.cur += roundup(size, 1 << MIN_OCQP_SHIFT);
397 if (rdev->stats.ocqp.cur > rdev->stats.ocqp.max)
398 rdev->stats.ocqp.max = rdev->stats.ocqp.cur;
399 mutex_unlock(&rdev->stats.lock);
400 }
436 return (u32)addr; 401 return (u32)addr;
437} 402}
438 403
439void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size) 404void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size)
440{ 405{
441 PDBG("%s addr 0x%x size %d\n", __func__, addr, size); 406 PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
407 mutex_lock(&rdev->stats.lock);
408 rdev->stats.ocqp.cur -= roundup(size, 1 << MIN_OCQP_SHIFT);
409 mutex_unlock(&rdev->stats.lock);
442 gen_pool_free(rdev->ocqp_pool, (unsigned long)addr, size); 410 gen_pool_free(rdev->ocqp_pool, (unsigned long)addr, size);
443} 411}
444 412