Commit 62a97a56 authored by Eric Farman's avatar Eric Farman Committed by Heiko Carstens

vfio/ccw: pass page count to page_array struct

The allocation of our page_array struct calculates the number
of 4K pages that would be needed to hold a certain number of
bytes. But, since the number of pages that will be pinned is
also calculated by the length of the IDAL, this logic is
unnecessary. Let's pass that information in directly, and
avoid the math within the allocator.

Also, let's make this two allocations instead of one,
to make it apparent what's happening within here.
Signed-off-by: default avatarEric Farman <farman@linux.ibm.com>
Reviewed-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent 4b946d65
...@@ -43,7 +43,7 @@ struct ccwchain { ...@@ -43,7 +43,7 @@ struct ccwchain {
* page_array_alloc() - alloc memory for page array * page_array_alloc() - alloc memory for page array
* @pa: page_array on which to perform the operation * @pa: page_array on which to perform the operation
* @iova: target guest physical address * @iova: target guest physical address
* @len: number of bytes that should be pinned from @iova * @len: number of pages that should be pinned from @iova
* *
* Attempt to allocate memory for page array. * Attempt to allocate memory for page array.
* *
...@@ -63,18 +63,20 @@ static int page_array_alloc(struct page_array *pa, u64 iova, unsigned int len) ...@@ -63,18 +63,20 @@ static int page_array_alloc(struct page_array *pa, u64 iova, unsigned int len)
if (pa->pa_nr || pa->pa_iova) if (pa->pa_nr || pa->pa_iova)
return -EINVAL; return -EINVAL;
pa->pa_nr = ((iova & ~PAGE_MASK) + len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; if (len == 0)
if (!pa->pa_nr)
return -EINVAL; return -EINVAL;
pa->pa_iova = kcalloc(pa->pa_nr, pa->pa_nr = len;
sizeof(*pa->pa_iova) + sizeof(*pa->pa_page),
GFP_KERNEL); pa->pa_iova = kcalloc(len, sizeof(*pa->pa_iova), GFP_KERNEL);
if (unlikely(!pa->pa_iova)) { if (!pa->pa_iova)
pa->pa_nr = 0; return -ENOMEM;
pa->pa_page = kcalloc(len, sizeof(*pa->pa_page), GFP_KERNEL);
if (!pa->pa_page) {
kfree(pa->pa_iova);
return -ENOMEM; return -ENOMEM;
} }
pa->pa_page = (struct page **)&pa->pa_iova[pa->pa_nr];
pa->pa_iova[0] = iova; pa->pa_iova[0] = iova;
pa->pa_page[0] = NULL; pa->pa_page[0] = NULL;
...@@ -167,6 +169,7 @@ static int page_array_pin(struct page_array *pa, struct vfio_device *vdev) ...@@ -167,6 +169,7 @@ static int page_array_pin(struct page_array *pa, struct vfio_device *vdev)
static void page_array_unpin_free(struct page_array *pa, struct vfio_device *vdev) static void page_array_unpin_free(struct page_array *pa, struct vfio_device *vdev)
{ {
page_array_unpin(pa, vdev, pa->pa_nr); page_array_unpin(pa, vdev, pa->pa_nr);
kfree(pa->pa_page);
kfree(pa->pa_iova); kfree(pa->pa_iova);
} }
...@@ -545,7 +548,7 @@ static int ccwchain_fetch_ccw(struct ccw1 *ccw, ...@@ -545,7 +548,7 @@ static int ccwchain_fetch_ccw(struct ccw1 *ccw,
* required for the data transfer, since we only only support * required for the data transfer, since we only only support
* 4K IDAWs today. * 4K IDAWs today.
*/ */
ret = page_array_alloc(pa, iova, bytes); ret = page_array_alloc(pa, iova, idaw_nr);
if (ret < 0) if (ret < 0)
goto out_free_idaws; goto out_free_idaws;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment