Skip to content

Commit a3cdcbf

Browse files
Yevgeny PetrilinRoland Dreier
authored andcommitted
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 <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent f6bccf6 commit a3cdcbf

File tree

5 files changed

+129
-18
lines changed

5 files changed

+129
-18
lines changed

drivers/infiniband/hw/mlx4/qp.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
451451
struct ib_qp_init_attr *init_attr,
452452
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
453453
{
454+
int qpn;
454455
int err;
455456

456457
mutex_init(&qp->mutex);
@@ -545,9 +546,17 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
545546
}
546547
}
547548

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);
549558
if (err)
550-
goto err_wrid;
559+
goto err_qpn;
551560

552561
/*
553562
* 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,
560569

561570
return 0;
562571

572+
err_qpn:
573+
if (!sqpn)
574+
mlx4_qp_release_range(dev->dev, qpn, 1);
575+
563576
err_wrid:
564577
if (pd->uobject) {
565578
if (!init_attr->srq)
@@ -655,6 +668,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
655668
mlx4_ib_unlock_cqs(send_cq, recv_cq);
656669

657670
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+
658675
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
659676

660677
if (is_user) {

drivers/net/mlx4/alloc.c

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,82 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
6565

6666
void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
6767
{
68+
mlx4_bitmap_free_range(bitmap, obj, 1);
69+
}
70+
71+
static 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+
77+
again:
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+
100+
u32 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+
135+
void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
136+
{
137+
u32 i;
138+
68139
obj &= bitmap->max - 1;
69140

70141
spin_lock(&bitmap->lock);
71-
clear_bit(obj, bitmap->table);
142+
for (i = 0; i < cnt; i++)
143+
clear_bit(obj + i, bitmap->table);
72144
bitmap->last = min(bitmap->last, obj);
73145
bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
74146
spin_unlock(&bitmap->lock);

drivers/net/mlx4/mlx4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
288288

289289
u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap);
290290
void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj);
291+
u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align);
292+
void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt);
291293
int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved);
292294
void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
293295

drivers/net/mlx4/qp.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,42 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
147147
}
148148
EXPORT_SYMBOL_GPL(mlx4_qp_modify);
149149

150-
int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp)
150+
int 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+
}
163+
EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
164+
165+
void 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+
}
174+
EXPORT_SYMBOL_GPL(mlx4_qp_release_range);
175+
176+
int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp)
151177
{
152178
struct mlx4_priv *priv = mlx4_priv(dev);
153179
struct mlx4_qp_table *qp_table = &priv->qp_table;
154180
int err;
155181

156-
if (sqpn)
157-
qp->qpn = sqpn;
158-
else {
159-
qp->qpn = mlx4_bitmap_alloc(&qp_table->bitmap);
160-
if (qp->qpn == -1)
161-
return -ENOMEM;
162-
}
182+
if (!qpn)
183+
return -EINVAL;
184+
185+
qp->qpn = qpn;
163186

164187
err = mlx4_table_get(dev, &qp_table->qp_table, qp->qpn);
165188
if (err)
@@ -208,9 +231,6 @@ int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp)
208231
mlx4_table_put(dev, &qp_table->qp_table, qp->qpn);
209232

210233
err_out:
211-
if (!sqpn)
212-
mlx4_bitmap_free(&qp_table->bitmap, qp->qpn);
213-
214234
return err;
215235
}
216236
EXPORT_SYMBOL_GPL(mlx4_qp_alloc);
@@ -239,9 +259,6 @@ void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp)
239259
mlx4_table_put(dev, &qp_table->altc_table, qp->qpn);
240260
mlx4_table_put(dev, &qp_table->auxc_table, qp->qpn);
241261
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);
245262
}
246263
EXPORT_SYMBOL_GPL(mlx4_qp_free);
247264

include/linux/mlx4/device.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,10 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
400400
int collapsed);
401401
void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
402402

403-
int mlx4_qp_alloc(struct mlx4_dev *dev, int sqpn, struct mlx4_qp *qp);
403+
int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base);
404+
void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
405+
406+
int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp);
404407
void mlx4_qp_free(struct mlx4_dev *dev, struct mlx4_qp *qp);
405408

406409
int mlx4_srq_alloc(struct mlx4_dev *dev, u32 pdn, struct mlx4_mtt *mtt,

0 commit comments

Comments
 (0)