Skip to content

Commit

Permalink
IB/mlx4: Use vmalloc for WR buffers when needed
Browse files Browse the repository at this point in the history
There are several hits that WR buffer allocation(kmalloc) failed.
It failed at order 3 and/or 4 contigous pages allocation. At the same time
there are actually 100MB+ free memory but well fragmented.
So try vmalloc when kmalloc failed.

Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com>
Acked-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Wengang Wang authored and Doug Ledford committed Dec 8, 2015
1 parent 73d4da7 commit 0ef2f05
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 9 deletions.
19 changes: 13 additions & 6 deletions drivers/infiniband/hw/mlx4/qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/log2.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/vmalloc.h>

#include <rdma/ib_cache.h>
#include <rdma/ib_pack.h>
Expand Down Expand Up @@ -795,8 +796,14 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (err)
goto err_mtt;

qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof (u64), gfp);
qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof (u64), gfp);
qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof(u64), gfp);
if (!qp->sq.wrid)
qp->sq.wrid = __vmalloc(qp->sq.wqe_cnt * sizeof(u64),
gfp, PAGE_KERNEL);
qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof(u64), gfp);
if (!qp->rq.wrid)
qp->rq.wrid = __vmalloc(qp->rq.wqe_cnt * sizeof(u64),
gfp, PAGE_KERNEL);
if (!qp->sq.wrid || !qp->rq.wrid) {
err = -ENOMEM;
goto err_wrid;
Expand Down Expand Up @@ -886,8 +893,8 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
if (qp_has_rq(init_attr))
mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
} else {
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
kvfree(qp->sq.wrid);
kvfree(qp->rq.wrid);
}

err_mtt:
Expand Down Expand Up @@ -1062,8 +1069,8 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
&qp->db);
ib_umem_release(qp->umem);
} else {
kfree(qp->sq.wrid);
kfree(qp->rq.wrid);
kvfree(qp->sq.wrid);
kvfree(qp->rq.wrid);
if (qp->mlx4_ib_qp_type & (MLX4_IB_QPT_PROXY_SMI_OWNER |
MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI))
free_proxy_bufs(&dev->ib_dev, qp);
Expand Down
11 changes: 8 additions & 3 deletions drivers/infiniband/hw/mlx4/srq.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/mlx4/qp.h>
#include <linux/mlx4/srq.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>

#include "mlx4_ib.h"
#include "user.h"
Expand Down Expand Up @@ -172,8 +173,12 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,

srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL);
if (!srq->wrid) {
err = -ENOMEM;
goto err_mtt;
srq->wrid = __vmalloc(srq->msrq.max * sizeof(u64),
GFP_KERNEL, PAGE_KERNEL);
if (!srq->wrid) {
err = -ENOMEM;
goto err_mtt;
}
}
}

Expand Down Expand Up @@ -204,7 +209,7 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
if (pd->uobject)
mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db);
else
kfree(srq->wrid);
kvfree(srq->wrid);

err_mtt:
mlx4_mtt_cleanup(dev->dev, &srq->mtt);
Expand Down

0 comments on commit 0ef2f05

Please sign in to comment.