diff options
author | Vipul Pandya <vipul@chelsio.com> | 2012-05-18 05:59:32 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-05-18 16:22:36 -0400 |
commit | ec3eead217181d7360a11317a888ceb30807867c (patch) | |
tree | a03f11c906567206293bfed251542c0d0da05e43 /drivers/infiniband/hw/cxgb4 | |
parent | d716a2a014ad199362a59004b5ab932030a213ff (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/Makefile | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/device.c | 37 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/id_table.c | 112 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 35 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/mem.c | 10 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/provider.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/hw/cxgb4/resource.c | 148 |
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 | ||
3 | obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o | 3 | obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o |
4 | 4 | ||
5 | iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o | 5 | iw_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 | */ | ||
44 | u32 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 | |||
71 | void 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 | |||
83 | int 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 | |||
109 | void 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 | |||
84 | struct 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 | |||
82 | struct c4iw_resource { | 93 | struct 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 | ||
91 | struct c4iw_qid_list { | 99 | struct 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 | ||
112 | struct c4iw_stats { | 121 | struct 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 | ||
767 | u32 c4iw_id_alloc(struct c4iw_id_table *alloc); | ||
768 | void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj); | ||
769 | int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num, | ||
770 | u32 reserved, u32 flags); | ||
771 | void c4iw_id_table_free(struct c4iw_id_table *alloc); | ||
772 | |||
758 | typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb); | 773 | typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb); |
759 | 774 | ||
760 | int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, | 775 | int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new, |
761 | struct l2t_entry *l2t); | 776 | struct l2t_entry *l2t); |
762 | void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid, | 777 | void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid, |
763 | struct c4iw_dev_ucontext *uctx); | 778 | struct c4iw_dev_ucontext *uctx); |
764 | u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock); | 779 | u32 c4iw_get_resource(struct c4iw_id_table *id_table); |
765 | void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock); | 780 | void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry); |
766 | int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid); | 781 | int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid); |
767 | int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev); | 782 | int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev); |
768 | int c4iw_pblpool_create(struct c4iw_rdev *rdev); | 783 | int 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 | 38 | static int c4iw_init_qid_table(struct c4iw_rdev *rdev) |
44 | |||
45 | static 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 | |||
93 | static 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 | |||
100 | static 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 | |||
108 | static 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) | |||
127 | int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid) | 56 | int 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; |
144 | pdid_err: | 71 | pdid_err: |
145 | kfifo_free(&rdev->resource.qid_fifo); | 72 | c4iw_id_table_free(&rdev->resource.qid_table); |
146 | qid_err: | 73 | qid_err: |
147 | kfifo_free(&rdev->resource.tpt_fifo); | 74 | c4iw_id_table_free(&rdev->resource.tpt_table); |
148 | tpt_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 | */ |
155 | u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock) | 82 | u32 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 | ||
164 | void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock) | 91 | void 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 | ||
170 | u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx) | 97 | u32 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 | ||
312 | void c4iw_destroy_resource(struct c4iw_resource *rscp) | 237 | void 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 | ||