diff options
Diffstat (limited to 'drivers/vfio/iova_bitmap.c')
| -rw-r--r-- | drivers/vfio/iova_bitmap.c | 33 | 
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);  | 
