aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/cxgb4
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2012-05-18 05:59:32 -0400
committerRoland Dreier <roland@purestorage.com>2012-05-18 16:22:36 -0400
commitec3eead217181d7360a11317a888ceb30807867c (patch)
treea03f11c906567206293bfed251542c0d0da05e43 /drivers/infiniband/hw/cxgb4
parentd716a2a014ad199362a59004b5ab932030a213ff (diff)
RDMA/cxgb4: Remove kfifo usage
Using kfifos for ID management was limiting the number of QPs and preventing NP384 MPI jobs. So replace it with a simple bitmap allocator. Remove IDs from the IDR tables before deallocating them. This bug was causing the BUG_ON() in insert_handle() to fire because the ID was getting reused before being removed from the IDR table. Signed-off-by: Vipul Pandya <vipul@chelsio.com> Signed-off-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/cxgb4')
-rw-r--r--drivers/infiniband/hw/cxgb4/Makefile2
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c37
-rw-r--r--drivers/infiniband/hw/cxgb4/id_table.c112
-rw-r--r--drivers/infiniband/hw/cxgb4/iw_cxgb4.h35
-rw-r--r--drivers/infiniband/hw/cxgb4/mem.c10
-rw-r--r--drivers/infiniband/hw/cxgb4/provider.c9
-rw-r--r--drivers/infiniband/hw/cxgb4/resource.c148
7 files changed, 203 insertions, 150 deletions
diff --git a/drivers/infiniband/hw/cxgb4/Makefile b/drivers/infiniband/hw/cxgb4/Makefile
index 46b878ca2c3b..e11cf7299945 100644
--- a/drivers/infiniband/hw/cxgb4/Makefile
+++ b/drivers/infiniband/hw/cxgb4/Makefile
@@ -2,4 +2,4 @@ ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
2 2
3obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o 3obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
4 4
5iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o 5iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o id_table.o
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 854562915413..c8fd1d8b20e6 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -252,25 +252,26 @@ static int stats_show(struct seq_file *seq, void *v)
252{ 252{
253 struct c4iw_dev *dev = seq->private; 253 struct c4iw_dev *dev = seq->private;
254 254
255 seq_printf(seq, " Object: %10s %10s %10s\n", "Total", "Current", "Max"); 255 seq_printf(seq, " Object: %10s %10s %10s %10s\n", "Total", "Current",
256 seq_printf(seq, " PDID: %10llu %10llu %10llu\n", 256 "Max", "Fail");
257 seq_printf(seq, " PDID: %10llu %10llu %10llu %10llu\n",
257 dev->rdev.stats.pd.total, dev->rdev.stats.pd.cur, 258 dev->rdev.stats.pd.total, dev->rdev.stats.pd.cur,
258 dev->rdev.stats.pd.max); 259 dev->rdev.stats.pd.max, dev->rdev.stats.pd.fail);
259 seq_printf(seq, " QID: %10llu %10llu %10llu\n", 260 seq_printf(seq, " QID: %10llu %10llu %10llu %10llu\n",
260 dev->rdev.stats.qid.total, dev->rdev.stats.qid.cur, 261 dev->rdev.stats.qid.total, dev->rdev.stats.qid.cur,
261 dev->rdev.stats.qid.max); 262 dev->rdev.stats.qid.max, dev->rdev.stats.qid.fail);
262 seq_printf(seq, " TPTMEM: %10llu %10llu %10llu\n", 263 seq_printf(seq, " TPTMEM: %10llu %10llu %10llu %10llu\n",
263 dev->rdev.stats.stag.total, dev->rdev.stats.stag.cur, 264 dev->rdev.stats.stag.total, dev->rdev.stats.stag.cur,
264 dev->rdev.stats.stag.max); 265 dev->rdev.stats.stag.max, dev->rdev.stats.stag.fail);
265 seq_printf(seq, " PBLMEM: %10llu %10llu %10llu\n", 266 seq_printf(seq, " PBLMEM: %10llu %10llu %10llu %10llu\n",
266 dev->rdev.stats.pbl.total, dev->rdev.stats.pbl.cur, 267 dev->rdev.stats.pbl.total, dev->rdev.stats.pbl.cur,
267 dev->rdev.stats.pbl.max); 268 dev->rdev.stats.pbl.max, dev->rdev.stats.pbl.fail);
268 seq_printf(seq, " RQTMEM: %10llu %10llu %10llu\n", 269 seq_printf(seq, " RQTMEM: %10llu %10llu %10llu %10llu\n",
269 dev->rdev.stats.rqt.total, dev->rdev.stats.rqt.cur, 270 dev->rdev.stats.rqt.total, dev->rdev.stats.rqt.cur,
270 dev->rdev.stats.rqt.max); 271 dev->rdev.stats.rqt.max, dev->rdev.stats.rqt.fail);
271 seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu\n", 272 seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu %10llu\n",
272 dev->rdev.stats.ocqp.total, dev->rdev.stats.ocqp.cur, 273 dev->rdev.stats.ocqp.total, dev->rdev.stats.ocqp.cur,
273 dev->rdev.stats.ocqp.max); 274 dev->rdev.stats.ocqp.max, dev->rdev.stats.ocqp.fail);
274 seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full); 275 seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full);
275 seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty); 276 seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty);
276 seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop); 277 seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop);
@@ -292,11 +293,17 @@ static ssize_t stats_clear(struct file *file, const char __user *buf,
292 293
293 mutex_lock(&dev->rdev.stats.lock); 294 mutex_lock(&dev->rdev.stats.lock);
294 dev->rdev.stats.pd.max = 0; 295 dev->rdev.stats.pd.max = 0;
296 dev->rdev.stats.pd.fail = 0;
295 dev->rdev.stats.qid.max = 0; 297 dev->rdev.stats.qid.max = 0;
298 dev->rdev.stats.qid.fail = 0;
296 dev->rdev.stats.stag.max = 0; 299 dev->rdev.stats.stag.max = 0;
300 dev->rdev.stats.stag.fail = 0;
297 dev->rdev.stats.pbl.max = 0; 301 dev->rdev.stats.pbl.max = 0;
302 dev->rdev.stats.pbl.fail = 0;
298 dev->rdev.stats.rqt.max = 0; 303 dev->rdev.stats.rqt.max = 0;
304 dev->rdev.stats.rqt.fail = 0;
299 dev->rdev.stats.ocqp.max = 0; 305 dev->rdev.stats.ocqp.max = 0;
306 dev->rdev.stats.ocqp.fail = 0;
300 dev->rdev.stats.db_full = 0; 307 dev->rdev.stats.db_full = 0;
301 dev->rdev.stats.db_empty = 0; 308 dev->rdev.stats.db_empty = 0;
302 dev->rdev.stats.db_drop = 0; 309 dev->rdev.stats.db_drop = 0;
@@ -350,8 +357,8 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
350 entry = list_entry(pos, struct c4iw_qid_list, entry); 357 entry = list_entry(pos, struct c4iw_qid_list, entry);
351 list_del_init(&entry->entry); 358 list_del_init(&entry->entry);
352 if (!(entry->qid & rdev->qpmask)) { 359 if (!(entry->qid & rdev->qpmask)) {
353 c4iw_put_resource(&rdev->resource.qid_fifo, entry->qid, 360 c4iw_put_resource(&rdev->resource.qid_table,
354 &rdev->resource.qid_fifo_lock); 361 entry->qid);
355 mutex_lock(&rdev->stats.lock); 362 mutex_lock(&rdev->stats.lock);
356 rdev->stats.qid.cur -= rdev->qpmask + 1; 363 rdev->stats.qid.cur -= rdev->qpmask + 1;
357 mutex_unlock(&rdev->stats.lock); 364 mutex_unlock(&rdev->stats.lock);
diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c
new file mode 100644
index 000000000000..f95e5df30db2
--- /dev/null
+++ b/drivers/infiniband/hw/cxgb4/id_table.c
@@ -0,0 +1,112 @@
1/*
2 * Copyright (c) 2011 Chelsio Communications. All rights reserved.
3 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
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 * Trivial bitmap-based allocator. If the random flag is set, the
40 * allocator is designed to:
41 * - pseudo-randomize the id returned such that it is not trivially predictable.
42 * - avoid reuse of recently used id (at the expense of predictability)
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 += random32() % 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 = random32() % 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}
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 6818659f2617..2d5b06b3217b 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -45,7 +45,6 @@
45#include <linux/kref.h> 45#include <linux/kref.h>
46#include <linux/timer.h> 46#include <linux/timer.h>
47#include <linux/io.h> 47#include <linux/io.h>
48#include <linux/kfifo.h>
49 48
50#include <asm/byteorder.h> 49#include <asm/byteorder.h>
51 50
@@ -79,13 +78,22 @@ static inline void *cplhdr(struct sk_buff *skb)
79 return skb->data; 78 return skb->data;
80} 79}
81 80
81#define C4IW_ID_TABLE_F_RANDOM 1 /* Pseudo-randomize the id's returned */
82#define C4IW_ID_TABLE_F_EMPTY 2 /* Table is initially empty */
83
84struct c4iw_id_table {
85 u32 flags;
86 u32 start; /* logical minimal id */
87 u32 last; /* hint for find */
88 u32 max;
89 spinlock_t lock;
90 unsigned long *table;
91};
92
82struct c4iw_resource { 93struct c4iw_resource {
83 struct kfifo tpt_fifo; 94 struct c4iw_id_table tpt_table;
84 spinlock_t tpt_fifo_lock; 95 struct c4iw_id_table qid_table;
85 struct kfifo qid_fifo; 96 struct c4iw_id_table pdid_table;
86 spinlock_t qid_fifo_lock;
87 struct kfifo pdid_fifo;
88 spinlock_t pdid_fifo_lock;
89}; 97};
90 98
91struct c4iw_qid_list { 99struct c4iw_qid_list {
@@ -107,6 +115,7 @@ struct c4iw_stat {
107 u64 total; 115 u64 total;
108 u64 cur; 116 u64 cur;
109 u64 max; 117 u64 max;
118 u64 fail;
110}; 119};
111 120
112struct c4iw_stats { 121struct c4iw_stats {
@@ -253,7 +262,7 @@ static inline int _insert_handle(struct c4iw_dev *rhp, struct idr *idr,
253 if (lock) 262 if (lock)
254 spin_lock_irq(&rhp->lock); 263 spin_lock_irq(&rhp->lock);
255 ret = idr_get_new_above(idr, handle, id, &newid); 264 ret = idr_get_new_above(idr, handle, id, &newid);
256 BUG_ON(newid != id); 265 BUG_ON(!ret && newid != id);
257 if (lock) 266 if (lock)
258 spin_unlock_irq(&rhp->lock); 267 spin_unlock_irq(&rhp->lock);
259 } while (ret == -EAGAIN); 268 } while (ret == -EAGAIN);
@@ -755,14 +764,20 @@ static inline int compute_wscale(int win)
755 return wscale; 764 return wscale;
756} 765}
757 766
767u32 c4iw_id_alloc(struct c4iw_id_table *alloc);
768void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj);
769int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
770 u32 reserved, u32 flags);
771void c4iw_id_table_free(struct c4iw_id_table *alloc);
772
758typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb); 773typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb);
759 774
760int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, 775int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
761 struct l2t_entry *l2t); 776 struct l2t_entry *l2t);
762void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid, 777void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid,
763 struct c4iw_dev_ucontext *uctx); 778 struct c4iw_dev_ucontext *uctx);
764u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock); 779u32 c4iw_get_resource(struct c4iw_id_table *id_table);
765void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock); 780void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry);
766int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid); 781int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid);
767int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev); 782int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev);
768int c4iw_pblpool_create(struct c4iw_rdev *rdev); 783int c4iw_pblpool_create(struct c4iw_rdev *rdev);
diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
index 2a87379f52a3..57e07c61ace2 100644
--- a/drivers/infiniband/hw/cxgb4/mem.c
+++ b/drivers/infiniband/hw/cxgb4/mem.c
@@ -131,8 +131,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
131 stag_idx = (*stag) >> 8; 131 stag_idx = (*stag) >> 8;
132 132
133 if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) { 133 if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
134 stag_idx = c4iw_get_resource(&rdev->resource.tpt_fifo, 134 stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
135 &rdev->resource.tpt_fifo_lock);
136 if (!stag_idx) 135 if (!stag_idx)
137 return -ENOMEM; 136 return -ENOMEM;
138 mutex_lock(&rdev->stats.lock); 137 mutex_lock(&rdev->stats.lock);
@@ -171,8 +170,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
171 sizeof(tpt), &tpt); 170 sizeof(tpt), &tpt);
172 171
173 if (reset_tpt_entry) { 172 if (reset_tpt_entry) {
174 c4iw_put_resource(&rdev->resource.tpt_fifo, stag_idx, 173 c4iw_put_resource(&rdev->resource.tpt_table, stag_idx);
175 &rdev->resource.tpt_fifo_lock);
176 mutex_lock(&rdev->stats.lock); 174 mutex_lock(&rdev->stats.lock);
177 rdev->stats.stag.cur -= 32; 175 rdev->stats.stag.cur -= 32;
178 mutex_unlock(&rdev->stats.lock); 176 mutex_unlock(&rdev->stats.lock);
@@ -695,8 +693,8 @@ int c4iw_dealloc_mw(struct ib_mw *mw)
695 mhp = to_c4iw_mw(mw); 693 mhp = to_c4iw_mw(mw);
696 rhp = mhp->rhp; 694 rhp = mhp->rhp;
697 mmid = (mw->rkey) >> 8; 695 mmid = (mw->rkey) >> 8;
698 deallocate_window(&rhp->rdev, mhp->attr.stag);
699 remove_handle(rhp, &rhp->mmidr, mmid); 696 remove_handle(rhp, &rhp->mmidr, mmid);
697 deallocate_window(&rhp->rdev, mhp->attr.stag);
700 kfree(mhp); 698 kfree(mhp);
701 PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp); 699 PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
702 return 0; 700 return 0;
@@ -798,12 +796,12 @@ int c4iw_dereg_mr(struct ib_mr *ib_mr)
798 mhp = to_c4iw_mr(ib_mr); 796 mhp = to_c4iw_mr(ib_mr);
799 rhp = mhp->rhp; 797 rhp = mhp->rhp;
800 mmid = mhp->attr.stag >> 8; 798 mmid = mhp->attr.stag >> 8;
799 remove_handle(rhp, &rhp->mmidr, mmid);
801 dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size, 800 dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
802 mhp->attr.pbl_addr); 801 mhp->attr.pbl_addr);
803 if (mhp->attr.pbl_size) 802 if (mhp->attr.pbl_size)
804 c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr, 803 c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
805 mhp->attr.pbl_size << 3); 804 mhp->attr.pbl_size << 3);
806 remove_handle(rhp, &rhp->mmidr, mmid);
807 if (mhp->kva) 805 if (mhp->kva)
808 kfree((void *) (unsigned long) mhp->kva); 806 kfree((void *) (unsigned long) mhp->kva);
809 if (mhp->umem) 807 if (mhp->umem)
diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
index 8d58736f9b4f..fe98a0a55430 100644
--- a/drivers/infiniband/hw/cxgb4/provider.c
+++ b/drivers/infiniband/hw/cxgb4/provider.c
@@ -188,8 +188,7 @@ static int c4iw_deallocate_pd(struct ib_pd *pd)
188 php = to_c4iw_pd(pd); 188 php = to_c4iw_pd(pd);
189 rhp = php->rhp; 189 rhp = php->rhp;
190 PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid); 190 PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid);
191 c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, php->pdid, 191 c4iw_put_resource(&rhp->rdev.resource.pdid_table, php->pdid);
192 &rhp->rdev.resource.pdid_fifo_lock);
193 mutex_lock(&rhp->rdev.stats.lock); 192 mutex_lock(&rhp->rdev.stats.lock);
194 rhp->rdev.stats.pd.cur--; 193 rhp->rdev.stats.pd.cur--;
195 mutex_unlock(&rhp->rdev.stats.lock); 194 mutex_unlock(&rhp->rdev.stats.lock);
@@ -207,14 +206,12 @@ static struct ib_pd *c4iw_allocate_pd(struct ib_device *ibdev,
207 206
208 PDBG("%s ibdev %p\n", __func__, ibdev); 207 PDBG("%s ibdev %p\n", __func__, ibdev);
209 rhp = (struct c4iw_dev *) ibdev; 208 rhp = (struct c4iw_dev *) ibdev;
210 pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_fifo, 209 pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_table);
211 &rhp->rdev.resource.pdid_fifo_lock);
212 if (!pdid) 210 if (!pdid)
213 return ERR_PTR(-EINVAL); 211 return ERR_PTR(-EINVAL);
214 php = kzalloc(sizeof(*php), GFP_KERNEL); 212 php = kzalloc(sizeof(*php), GFP_KERNEL);
215 if (!php) { 213 if (!php) {
216 c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, pdid, 214 c4iw_put_resource(&rhp->rdev.resource.pdid_table, pdid);
217 &rhp->rdev.resource.pdid_fifo_lock);
218 return ERR_PTR(-ENOMEM); 215 return ERR_PTR(-ENOMEM);
219 } 216 }
220 php->pdid = pdid; 217 php->pdid = pdid;
diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
index 1b948d192d32..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,8 +108,7 @@ 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;
188 mutex_lock(&rdev->stats.lock); 114 mutex_lock(&rdev->stats.lock);
@@ -252,8 +178,7 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
252 qid = entry->qid; 178 qid = entry->qid;
253 kfree(entry); 179 kfree(entry);
254 } else { 180 } else {
255 qid = c4iw_get_resource(&rdev->resource.qid_fifo, 181 qid = c4iw_get_resource(&rdev->resource.qid_table);
256 &rdev->resource.qid_fifo_lock);
257 if (!qid) 182 if (!qid)
258 goto out; 183 goto out;
259 mutex_lock(&rdev->stats.lock); 184 mutex_lock(&rdev->stats.lock);
@@ -311,9 +236,9 @@ void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qid,
311 236
312void c4iw_destroy_resource(struct c4iw_resource *rscp) 237void c4iw_destroy_resource(struct c4iw_resource *rscp)
313{ 238{
314 kfifo_free(&rscp->tpt_fifo); 239 c4iw_id_table_free(&rscp->tpt_table);
315 kfifo_free(&rscp->qid_fifo); 240 c4iw_id_table_free(&rscp->qid_table);
316 kfifo_free(&rscp->pdid_fifo); 241 c4iw_id_table_free(&rscp->pdid_table);
317} 242}
318 243
319/* 244/*
@@ -326,16 +251,14 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
326{ 251{
327 unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size); 252 unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
328 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);
329 if (!addr) 254 mutex_lock(&rdev->stats.lock);
330 printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
331 pci_name(rdev->lldi.pdev));
332 if (addr) { 255 if (addr) {
333 mutex_lock(&rdev->stats.lock);
334 rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT); 256 rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
335 if (rdev->stats.pbl.cur > rdev->stats.pbl.max) 257 if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
336 rdev->stats.pbl.max = rdev->stats.pbl.cur; 258 rdev->stats.pbl.max = rdev->stats.pbl.cur;
337 mutex_unlock(&rdev->stats.lock); 259 } else
338 } 260 rdev->stats.pbl.fail++;
261 mutex_unlock(&rdev->stats.lock);
339 return (u32)addr; 262 return (u32)addr;
340} 263}
341 264
@@ -401,13 +324,14 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
401 if (!addr) 324 if (!addr)
402 printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n", 325 printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
403 pci_name(rdev->lldi.pdev)); 326 pci_name(rdev->lldi.pdev));
327 mutex_lock(&rdev->stats.lock);
404 if (addr) { 328 if (addr) {
405 mutex_lock(&rdev->stats.lock);
406 rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT); 329 rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
407 if (rdev->stats.rqt.cur > rdev->stats.rqt.max) 330 if (rdev->stats.rqt.cur > rdev->stats.rqt.max)
408 rdev->stats.rqt.max = rdev->stats.rqt.cur; 331 rdev->stats.rqt.max = rdev->stats.rqt.cur;
409 mutex_unlock(&rdev->stats.lock); 332 } else
410 } 333 rdev->stats.rqt.fail++;
334 mutex_unlock(&rdev->stats.lock);
411 return (u32)addr; 335 return (u32)addr;
412} 336}
413 337