Commit 255efcae authored by Gal Pressman's avatar Gal Pressman Committed by Jason Gunthorpe
Browse files

RDMA/efa: Use kvzalloc instead of kzalloc with fallback



Use kvzalloc which attempts to allocate a physically continuous buffer and
fallbacks to virtually continuous on failure instead of open coding it in
the driver.

The is_vmalloc_addr function is used to determine whether the buffer is
physically continuous or not (which determines direct vs indirect MR
registration mode).

Suggested-by: default avatarJason Gunthorpe <jgg@ziepe.ca>
Reviewed-by: default avatarFiras JahJah <firasj@amazon.com>
Reviewed-by: default avatarYossi Leybovich <sleybo@amazon.com>
Signed-off-by: default avatarGal Pressman <galpress@amazon.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 5f5e4eb4
Loading
Loading
Loading
Loading
+21 −25
Original line number Original line Diff line number Diff line
@@ -1285,30 +1285,30 @@ static int pbl_create(struct efa_dev *dev,
	int err;
	int err;


	pbl->pbl_buf_size_in_bytes = hp_cnt * EFA_CHUNK_PAYLOAD_PTR_SIZE;
	pbl->pbl_buf_size_in_bytes = hp_cnt * EFA_CHUNK_PAYLOAD_PTR_SIZE;
	pbl->pbl_buf = kzalloc(pbl->pbl_buf_size_in_bytes,
	pbl->pbl_buf = kvzalloc(pbl->pbl_buf_size_in_bytes, GFP_KERNEL);
			       GFP_KERNEL | __GFP_NOWARN);
	if (!pbl->pbl_buf)
	if (pbl->pbl_buf) {
		return -ENOMEM;
		pbl->physically_continuous = 1;

	if (is_vmalloc_addr(pbl->pbl_buf)) {
		pbl->physically_continuous = 0;
		err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt,
		err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt,
					hp_shift);
					hp_shift);
		if (err)
		if (err)
			goto err_continuous;
			goto err_free;
		err = pbl_continuous_initialize(dev, pbl);

		err = pbl_indirect_initialize(dev, pbl);
		if (err)
		if (err)
			goto err_continuous;
			goto err_free;
	} else {
	} else {
		pbl->physically_continuous = 0;
		pbl->physically_continuous = 1;
		pbl->pbl_buf = vzalloc(pbl->pbl_buf_size_in_bytes);
		if (!pbl->pbl_buf)
			return -ENOMEM;

		err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt,
		err = umem_to_page_list(dev, umem, pbl->pbl_buf, hp_cnt,
					hp_shift);
					hp_shift);
		if (err)
		if (err)
			goto err_indirect;
			goto err_free;
		err = pbl_indirect_initialize(dev, pbl);

		err = pbl_continuous_initialize(dev, pbl);
		if (err)
		if (err)
			goto err_indirect;
			goto err_free;
	}
	}


	ibdev_dbg(&dev->ibdev,
	ibdev_dbg(&dev->ibdev,
@@ -1317,24 +1317,20 @@ static int pbl_create(struct efa_dev *dev,


	return 0;
	return 0;


err_continuous:
err_free:
	kfree(pbl->pbl_buf);
	kvfree(pbl->pbl_buf);
	return err;
err_indirect:
	vfree(pbl->pbl_buf);
	return err;
	return err;
}
}


static void pbl_destroy(struct efa_dev *dev, struct pbl_context *pbl)
static void pbl_destroy(struct efa_dev *dev, struct pbl_context *pbl)
{
{
	if (pbl->physically_continuous) {
	if (pbl->physically_continuous)
		dma_unmap_single(&dev->pdev->dev, pbl->phys.continuous.dma_addr,
		dma_unmap_single(&dev->pdev->dev, pbl->phys.continuous.dma_addr,
				 pbl->pbl_buf_size_in_bytes, DMA_TO_DEVICE);
				 pbl->pbl_buf_size_in_bytes, DMA_TO_DEVICE);
		kfree(pbl->pbl_buf);
	else
	} else {
		pbl_indirect_terminate(dev, pbl);
		pbl_indirect_terminate(dev, pbl);
		vfree(pbl->pbl_buf);

	}
	kvfree(pbl->pbl_buf);
}
}


static int efa_create_inline_pbl(struct efa_dev *dev, struct efa_mr *mr,
static int efa_create_inline_pbl(struct efa_dev *dev, struct efa_mr *mr,