aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.co.il>2008-10-10 15:01:37 -0400
committerRoland Dreier <rolandd@cisco.com>2008-10-10 15:01:37 -0400
commita3cdcbfa8fb1fccfe48d359da86e99546610c562 (patch)
treea25715b6e9169568c53f80dc9333e024f389b383
parentf6bccf695431da0e9bd773550ae91b8cb9ffb227 (diff)
mlx4_core: Add QP range reservation support
To allow allocating an aligned range of consecutive QP numbers, add an interface to reserve an aligned range of QP numbers and have the QP allocation function always take a QP number. This will be used for RSS support in the mlx4_en Ethernet driver and also potentially by IPoIB RSS support. Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c21
-rw-r--r--drivers/net/mlx4/alloc.c74
-rw-r--r--drivers/net/mlx4/mlx4.h2
-rw-r--r--drivers/net/mlx4/qp.c45
-rw-r--r--include/linux/mlx4/device.h5
5 files changed, 129 insertions, 18 deletions
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index baa01deb2436..39167a797f99 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -451,6 +451,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
451 struct ib_qp_init_attr *init_attr, 451 struct ib_qp_init_attr *init_attr,
452 struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp) 452 struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
453{ 453{
454 int qpn;
454 int err; 455 int err;
455 456
456 mutex_init(&qp->mutex); 457 mutex_init(&qp->mutex);
@@ -545,9 +546,17 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
545 } 546 }
546 } 547 }
547 548
548 err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp); 549 if (sqpn) {
550 qpn = sqpn;
551 } else {
552 err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
553 if (err)
554 goto err_wrid;
555 }
556
557 err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp);
549 if (err) 558 if (err)
550 goto err_wrid; 559 goto err_qpn;
551 560
552 /* 561 /*
553 * Hardware wants QPN written in big-endian order (after 562 * Hardware wants QPN written in big-endian order (after
@@ -560,6 +569,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
560 569
561 return 0; 570 return 0;
562 571
572err_qpn:
573 if (!sqpn)
574 mlx4_qp_release_range(dev->dev, qpn, 1);
575
563err_wrid: 576err_wrid:
564 if (pd->uobject) { 577 if (pd->uobject) {
565 if (!init_attr->srq) 578 if (!init_attr->srq)
@@ -655,6 +668,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
655 mlx4_ib_unlock_cqs(send_cq, recv_cq); 668 mlx4_ib_unlock_cqs(send_cq, recv_cq);
656 669
657 mlx4_qp_free(dev->dev, &qp->mqp); 670 mlx4_qp_free(dev->dev, &qp->mqp);
671
672 if (!is_sqp(dev, qp))
673 mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
674
658 mlx4_mtt_cleanup(dev->dev, &qp->mtt); 675 mlx4_mtt_cleanup(dev->dev, &qp->mtt);
659 676
660 if (is_user) { 677 if (is_user) {
diff --git a/drivers/net/mlx4/alloc.c b/drivers/net/mlx4/alloc.c
index 096bca54bcf7..e6c0d5bb5dcb 100644
--- a/drivers/net/mlx4/alloc.c
+++ b/drivers/net/mlx4/alloc.c
@@ -65,10 +65,82 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
65 65
66void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj) 66void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
67{ 67{
68 mlx4_bitmap_free_range(bitmap, obj, 1);
69}
70
71static unsigned long find_aligned_range(unsigned long *bitmap,
72 u32 start, u32 nbits,
73 int len, int align)
74{
75 unsigned long end, i;
76
77again:
78 start = ALIGN(start, align);
79
80 while ((start < nbits) && test_bit(start, bitmap))
81 start += align;
82
83 if (start >= nbits)
84 return -1;
85
86 end = start+len;
87 if (end > nbits)
88 return -1;
89
90 for (i = start + 1; i < end; i++) {
91 if (test_bit(i, bitmap)) {
92 start = i + 1;
93 goto again;
94 }
95 }
96
97 return start;
98}
99
100u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
101{
102 u32 obj, i;
103
104 if (likely(cnt == 1 && align == 1))
105 return mlx4_bitmap_alloc(bitmap);
106
107 spin_lock(&bitmap->lock);
108
109 obj = find_aligned_range(bitmap->table, bitmap->last,
110 bitmap->max, cnt, align);
111 if (obj >= bitmap->max) {
112 bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
113 obj = find_aligned_range(bitmap->table, 0,
114 bitmap->max,
115 cnt, align);
116 }
117
118 if (obj < bitmap->max) {
119 for (i = 0; i < cnt; i++)
120 set_bit(obj + i, bitmap->table);
121 if (obj == bitmap->last) {
122 bitmap->last = (obj + cnt);
123 if (bitmap->last >= bitmap->max)
124 bitmap->last = 0;
125 }
126 obj |= bitmap->top;
127 } else
128 obj = -1;
129
130 spin_unlock(&bitmap->lock);
131
132 return obj;
133}
134
135void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
136{
137 u32 i;
138
68 obj &= bitmap->max - 1; 139 obj &= bitmap->max - 1;
69 140
70 spin_lock(&bitmap->lock); 141 spin_lock(&bitmap->lock);
71 clear_bit(obj, bitmap->table); 142 for (i = 0; i < cnt; i++)
143 clear_bit(obj + i, bitmap->table);
72 bitmap->last = min(bitmap->last, obj); 144 bitmap->last = min(bitmap->last, obj);
73 bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask; 145 bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
74 spin_unlock(&bitmap->lock); 146 spin_unlock(&bitmap->lock);
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 5337e3ac3e78..b55ddab73f66 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -288,6 +288,8 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
288 288
289u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap); 289u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap);
290void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj); 290void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj);
291u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align);
292void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt);
291int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved); 293int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved);
292void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap); 294void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
293 295
diff --git a/drivers/net/mlx4/qp.c b/drivers/net/mlx4/qp.c
index c49a86044bf7..98e0c40ba368 100644
--- a/drivers/net/mlx4/qp.c
+++ b/drivers/net/mlx4/qp.c
@@ -147,19 +147,42 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
147} 147}
148EXPORT_SYMBOL_GPL(mlx4_qp_modify); 148EXPORT_SYMBOL_GPL(mlx4_qp_modify);
149 149
150int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp) 150int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
151{
152 struct mlx4_priv *priv = mlx4_priv(dev);
153 struct mlx4_qp_table *qp_table = &priv->qp_table;
154 int qpn;
155
156 qpn = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align);
157 if (qpn == -1)
158 return -ENOMEM;
159
160 *base = qpn;
161 return 0;
162}
163EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
164
165void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
166{
167 struct mlx4_priv *priv = mlx4_priv(dev);
168 struct mlx4_qp_table *qp_table = &priv->qp_table;
169 if (base_qpn < dev->caps.sqp_start + 8)
170 return;
171
172 mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
173}
174EXPORT_SYMBOL_GPL(mlx4_qp_release_range);
175
176int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
151{ 177{
152 struct mlx4_priv *priv = mlx4_priv(dev); 178 struct mlx4_priv *priv = mlx4_priv(dev);
153 struct mlx4_qp_table *qp_table = &priv->qp_table; 179 struct mlx4_qp_table *qp_table = &priv->qp_table;
154 int err; 180 int err;
155 181
156 if (sqpn) 182 if (!qpn)
157 qp->qpn = sqpn; 183 return -EINVAL;
158 else { 184
159 qp->qpn = mlx4_bitmap_alloc(&qp_table->bitmap); 185 qp->qpn = qpn;
160 if (qp->qpn == -1)
161 return -ENOMEM;
162 }
163 186
164 err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn); 187 err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn);
165 if (err) 188 if (err)
@@ -208,9 +231,6 @@ err_put_qp:
208 mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); 231 mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
209 232
210err_out: 233err_out:
211 if (!sqpn)
212 mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
213
214 return err; 234 return err;
215} 235}
216EXPORT_SYMBOL_GPL(mlx4_qp_alloc); 236EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
@@ -239,9 +259,6 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
239 mlx4_table_put(dev, &qp_table->altc_table, qp->qpn); 259 mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
240 mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn); 260 mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
241 mlx4_table_put(dev, &qp_table->qp_table, qp->qpn); 261 mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
242
243 if (qp->qpn >= dev->caps.sqp_start + 8)
244 mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
245} 262}
246EXPORT_SYMBOL_GPL(mlx4_qp_free); 263EXPORT_SYMBOL_GPL(mlx4_qp_free);
247 264
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index b2f944468313..d21e879f3c90 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -400,7 +400,10 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
400 int collapsed); 400 int collapsed);
401void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq); 401void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
402 402
403int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp); 403int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base);
404void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
405
406int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp);
404void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp); 407void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp);
405 408
406int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt, 409int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,