summaryrefslogtreecommitdiff
path: root/drivers/vfio/iova_bitmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/vfio/iova_bitmap.c')
-rw-r--r--drivers/vfio/iova_bitmap.c33
1 files changed, 17 insertions, 16 deletions
diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c
index 6631e8befe1b..0848f920efb7 100644
--- a/drivers/vfio/iova_bitmap.c
+++ b/drivers/vfio/iova_bitmap.c
@@ -5,6 +5,7 @@
*/
#include <linux/iova_bitmap.h>
#include <linux/mm.h>
+#include <linux/slab.h>
#include <linux/highmem.h>
#define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE)
@@ -295,11 +296,13 @@ void iova_bitmap_free(struct iova_bitmap *bitmap)
*/
static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap)
{
- unsigned long remaining;
+ unsigned long remaining, bytes;
+
+ bytes = (bitmap->mapped.npages << PAGE_SHIFT) - bitmap->mapped.pgoff;
remaining = bitmap->mapped_total_index - bitmap->mapped_base_index;
remaining = min_t(unsigned long, remaining,
- (bitmap->mapped.npages << PAGE_SHIFT) / sizeof(*bitmap->bitmap));
+ bytes / sizeof(*bitmap->bitmap));
return remaining;
}
@@ -394,29 +397,27 @@ int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque,
* Set the bits corresponding to the range [iova .. iova+length-1] in
* the user bitmap.
*
- * Return: The number of bits set.
*/
void iova_bitmap_set(struct iova_bitmap *bitmap,
unsigned long iova, size_t length)
{
struct iova_bitmap_map *mapped = &bitmap->mapped;
- unsigned long offset = (iova - mapped->iova) >> mapped->pgshift;
- unsigned long nbits = max_t(unsigned long, 1, length >> mapped->pgshift);
- unsigned long page_idx = offset / BITS_PER_PAGE;
- unsigned long page_offset = mapped->pgoff;
- void *kaddr;
-
- offset = offset % BITS_PER_PAGE;
+ unsigned long cur_bit = ((iova - mapped->iova) >>
+ mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE;
+ unsigned long last_bit = (((iova + length - 1) - mapped->iova) >>
+ mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE;
do {
- unsigned long size = min(BITS_PER_PAGE - offset, nbits);
+ unsigned int page_idx = cur_bit / BITS_PER_PAGE;
+ unsigned int offset = cur_bit % BITS_PER_PAGE;
+ unsigned int nbits = min(BITS_PER_PAGE - offset,
+ last_bit - cur_bit + 1);
+ void *kaddr;
kaddr = kmap_local_page(mapped->pages[page_idx]);
- bitmap_set(kaddr + page_offset, offset, size);
+ bitmap_set(kaddr, offset, nbits);
kunmap_local(kaddr);
- page_offset = offset = 0;
- nbits -= size;
- page_idx++;
- } while (nbits > 0);
+ cur_bit += nbits;
+ } while (cur_bit <= last_bit);
}
EXPORT_SYMBOL_GPL(iova_bitmap_set);