|
@@ -59,7 +59,7 @@ struct ib_mr *mlx4_ib_get_dma_mr(struct ib_pd *pd, int acc)
|
|
|
struct mlx4_ib_mr *mr;
|
|
struct mlx4_ib_mr *mr;
|
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
- mr = kmalloc(sizeof *mr, GFP_KERNEL);
|
|
|
|
|
|
|
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
|
|
|
if (!mr)
|
|
if (!mr)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
@@ -140,7 +140,7 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
|
|
int err;
|
|
int err;
|
|
|
int n;
|
|
int n;
|
|
|
|
|
|
|
|
- mr = kmalloc(sizeof *mr, GFP_KERNEL);
|
|
|
|
|
|
|
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
|
|
|
if (!mr)
|
|
if (!mr)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
@@ -271,11 +271,59 @@ release_mpt_entry:
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int
|
|
|
|
|
+mlx4_alloc_priv_pages(struct ib_device *device,
|
|
|
|
|
+ struct mlx4_ib_mr *mr,
|
|
|
|
|
+ int max_pages)
|
|
|
|
|
+{
|
|
|
|
|
+ int size = max_pages * sizeof(u64);
|
|
|
|
|
+ int add_size;
|
|
|
|
|
+ int ret;
|
|
|
|
|
+
|
|
|
|
|
+ add_size = max_t(int, MLX4_MR_PAGES_ALIGN - ARCH_KMALLOC_MINALIGN, 0);
|
|
|
|
|
+
|
|
|
|
|
+ mr->pages_alloc = kzalloc(size + add_size, GFP_KERNEL);
|
|
|
|
|
+ if (!mr->pages_alloc)
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
+
|
|
|
|
|
+ mr->pages = PTR_ALIGN(mr->pages_alloc, MLX4_MR_PAGES_ALIGN);
|
|
|
|
|
+
|
|
|
|
|
+ mr->page_map = dma_map_single(device->dma_device, mr->pages,
|
|
|
|
|
+ size, DMA_TO_DEVICE);
|
|
|
|
|
+
|
|
|
|
|
+ if (dma_mapping_error(device->dma_device, mr->page_map)) {
|
|
|
|
|
+ ret = -ENOMEM;
|
|
|
|
|
+ goto err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+err:
|
|
|
|
|
+ kfree(mr->pages_alloc);
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
|
|
|
|
+mlx4_free_priv_pages(struct mlx4_ib_mr *mr)
|
|
|
|
|
+{
|
|
|
|
|
+ if (mr->pages) {
|
|
|
|
|
+ struct ib_device *device = mr->ibmr.device;
|
|
|
|
|
+ int size = mr->max_pages * sizeof(u64);
|
|
|
|
|
+
|
|
|
|
|
+ dma_unmap_single(device->dma_device, mr->page_map,
|
|
|
|
|
+ size, DMA_TO_DEVICE);
|
|
|
|
|
+ kfree(mr->pages_alloc);
|
|
|
|
|
+ mr->pages = NULL;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
|
|
int mlx4_ib_dereg_mr(struct ib_mr *ibmr)
|
|
|
{
|
|
{
|
|
|
struct mlx4_ib_mr *mr = to_mmr(ibmr);
|
|
struct mlx4_ib_mr *mr = to_mmr(ibmr);
|
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
+ mlx4_free_priv_pages(mr);
|
|
|
|
|
+
|
|
|
ret = mlx4_mr_free(to_mdev(ibmr->device)->dev, &mr->mmr);
|
|
ret = mlx4_mr_free(to_mdev(ibmr->device)->dev, &mr->mmr);
|
|
|
if (ret)
|
|
if (ret)
|
|
|
return ret;
|
|
return ret;
|
|
@@ -362,7 +410,7 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
|
|
|
max_num_sg > MLX4_MAX_FAST_REG_PAGES)
|
|
max_num_sg > MLX4_MAX_FAST_REG_PAGES)
|
|
|
return ERR_PTR(-EINVAL);
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
|
|
|
|
- mr = kmalloc(sizeof *mr, GFP_KERNEL);
|
|
|
|
|
|
|
+ mr = kzalloc(sizeof(*mr), GFP_KERNEL);
|
|
|
if (!mr)
|
|
if (!mr)
|
|
|
return ERR_PTR(-ENOMEM);
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
@@ -371,18 +419,25 @@ struct ib_mr *mlx4_ib_alloc_mr(struct ib_pd *pd,
|
|
|
if (err)
|
|
if (err)
|
|
|
goto err_free;
|
|
goto err_free;
|
|
|
|
|
|
|
|
|
|
+ err = mlx4_alloc_priv_pages(pd->device, mr, max_num_sg);
|
|
|
|
|
+ if (err)
|
|
|
|
|
+ goto err_free_mr;
|
|
|
|
|
+
|
|
|
|
|
+ mr->max_pages = max_num_sg;
|
|
|
|
|
+
|
|
|
err = mlx4_mr_enable(dev->dev, &mr->mmr);
|
|
err = mlx4_mr_enable(dev->dev, &mr->mmr);
|
|
|
if (err)
|
|
if (err)
|
|
|
- goto err_mr;
|
|
|
|
|
|
|
+ goto err_free_pl;
|
|
|
|
|
|
|
|
mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key;
|
|
mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key;
|
|
|
mr->umem = NULL;
|
|
mr->umem = NULL;
|
|
|
|
|
|
|
|
return &mr->ibmr;
|
|
return &mr->ibmr;
|
|
|
|
|
|
|
|
-err_mr:
|
|
|
|
|
|
|
+err_free_pl:
|
|
|
|
|
+ mlx4_free_priv_pages(mr);
|
|
|
|
|
+err_free_mr:
|
|
|
(void) mlx4_mr_free(dev->dev, &mr->mmr);
|
|
(void) mlx4_mr_free(dev->dev, &mr->mmr);
|
|
|
-
|
|
|
|
|
err_free:
|
|
err_free:
|
|
|
kfree(mr);
|
|
kfree(mr);
|
|
|
return ERR_PTR(err);
|
|
return ERR_PTR(err);
|
|
@@ -528,3 +583,37 @@ int mlx4_ib_fmr_dealloc(struct ib_fmr *ibfmr)
|
|
|
|
|
|
|
|
return err;
|
|
return err;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+static int mlx4_set_page(struct ib_mr *ibmr, u64 addr)
|
|
|
|
|
+{
|
|
|
|
|
+ struct mlx4_ib_mr *mr = to_mmr(ibmr);
|
|
|
|
|
+
|
|
|
|
|
+ if (unlikely(mr->npages == mr->max_pages))
|
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
+
|
|
|
|
|
+ mr->pages[mr->npages++] = cpu_to_be64(addr | MLX4_MTT_FLAG_PRESENT);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int mlx4_ib_map_mr_sg(struct ib_mr *ibmr,
|
|
|
|
|
+ struct scatterlist *sg,
|
|
|
|
|
+ int sg_nents)
|
|
|
|
|
+{
|
|
|
|
|
+ struct mlx4_ib_mr *mr = to_mmr(ibmr);
|
|
|
|
|
+ int rc;
|
|
|
|
|
+
|
|
|
|
|
+ mr->npages = 0;
|
|
|
|
|
+
|
|
|
|
|
+ ib_dma_sync_single_for_cpu(ibmr->device, mr->page_map,
|
|
|
|
|
+ sizeof(u64) * mr->max_pages,
|
|
|
|
|
+ DMA_TO_DEVICE);
|
|
|
|
|
+
|
|
|
|
|
+ rc = ib_sg_to_pages(ibmr, sg, sg_nents, mlx4_set_page);
|
|
|
|
|
+
|
|
|
|
|
+ ib_dma_sync_single_for_device(ibmr->device, mr->page_map,
|
|
|
|
|
+ sizeof(u64) * mr->max_pages,
|
|
|
|
|
+ DMA_TO_DEVICE);
|
|
|
|
|
+
|
|
|
|
|
+ return rc;
|
|
|
|
|
+}
|