@@ -35,6 +35,9 @@ struct iova_bitmap_map {
3535 /* base IOVA representing bit 0 of the first page */
3636 unsigned long iova ;
3737
38+ /* mapped length */
39+ unsigned long length ;
40+
3841 /* page size order that each bit granules to */
3942 unsigned long pgshift ;
4043
@@ -113,9 +116,6 @@ struct iova_bitmap {
113116
114117 /* length of the IOVA range for the whole bitmap */
115118 size_t length ;
116-
117- /* length of the IOVA range set ahead the pinned pages */
118- unsigned long set_ahead_length ;
119119};
120120
121121/*
@@ -156,6 +156,8 @@ static unsigned long iova_bitmap_mapped_iova(struct iova_bitmap *bitmap)
156156 return bitmap -> iova + iova_bitmap_index_to_offset (bitmap , skip );
157157}
158158
159+ static unsigned long iova_bitmap_mapped_length (struct iova_bitmap * bitmap );
160+
159161/*
160162 * Pins the bitmap user pages for the current range window.
161163 * This is internal to IOVA bitmap and called when advancing the
@@ -206,6 +208,7 @@ static int iova_bitmap_get(struct iova_bitmap *bitmap)
206208 * aligned.
207209 */
208210 mapped -> pgoff = offset_in_page (addr );
211+ mapped -> length = iova_bitmap_mapped_length (bitmap );
209212 return 0 ;
210213}
211214
@@ -263,9 +266,6 @@ struct iova_bitmap *iova_bitmap_alloc(unsigned long iova, size_t length,
263266 goto err ;
264267 }
265268
266- rc = iova_bitmap_get (bitmap );
267- if (rc )
268- goto err ;
269269 return bitmap ;
270270
271271err :
@@ -338,65 +338,34 @@ static unsigned long iova_bitmap_mapped_length(struct iova_bitmap *bitmap)
338338}
339339
340340/*
341- * Returns true if there's not more data to iterate .
341+ * Returns true if [@iova..@iova+@length-1] is part of the mapped IOVA range .
342342 */
343- static bool iova_bitmap_done (struct iova_bitmap * bitmap )
343+ static bool iova_bitmap_mapped_range (struct iova_bitmap_map * mapped ,
344+ unsigned long iova , size_t length )
344345{
345- return bitmap -> mapped_base_index >= bitmap -> mapped_total_index ;
346- }
347-
348- static int iova_bitmap_set_ahead (struct iova_bitmap * bitmap ,
349- size_t set_ahead_length )
350- {
351- int ret = 0 ;
352-
353- while (set_ahead_length > 0 && !iova_bitmap_done (bitmap )) {
354- unsigned long length = iova_bitmap_mapped_length (bitmap );
355- unsigned long iova = iova_bitmap_mapped_iova (bitmap );
356-
357- ret = iova_bitmap_get (bitmap );
358- if (ret )
359- break ;
360-
361- length = min (length , set_ahead_length );
362- iova_bitmap_set (bitmap , iova , length );
363-
364- set_ahead_length -= length ;
365- bitmap -> mapped_base_index +=
366- iova_bitmap_offset_to_index (bitmap , length - 1 ) + 1 ;
367- iova_bitmap_put (bitmap );
368- }
369-
370- bitmap -> set_ahead_length = 0 ;
371- return ret ;
346+ return mapped -> npages &&
347+ (iova >= mapped -> iova &&
348+ (iova + length - 1 ) <= (mapped -> iova + mapped -> length - 1 ));
372349}
373350
374351/*
375- * Advances to the next range, releases the current pinned
352+ * Advances to a selected range, releases the current pinned
376353 * pages and pins the next set of bitmap pages.
377354 * Returns 0 on success or otherwise errno.
378355 */
379- static int iova_bitmap_advance (struct iova_bitmap * bitmap )
356+ static int iova_bitmap_advance_to (struct iova_bitmap * bitmap ,
357+ unsigned long iova )
380358{
381- unsigned long iova = iova_bitmap_mapped_length (bitmap ) - 1 ;
382- unsigned long count = iova_bitmap_offset_to_index (bitmap , iova ) + 1 ;
359+ unsigned long index ;
383360
384- bitmap -> mapped_base_index += count ;
361+ index = iova_bitmap_offset_to_index (bitmap , iova - bitmap -> iova );
362+ if (index >= bitmap -> mapped_total_index )
363+ return - EINVAL ;
364+ bitmap -> mapped_base_index = index ;
385365
386366 iova_bitmap_put (bitmap );
387- if (iova_bitmap_done (bitmap ))
388- return 0 ;
389-
390- /* Iterate, set and skip any bits requested for next iteration */
391- if (bitmap -> set_ahead_length ) {
392- int ret ;
393-
394- ret = iova_bitmap_set_ahead (bitmap , bitmap -> set_ahead_length );
395- if (ret )
396- return ret ;
397- }
398367
399- /* When advancing the index we pin the next set of bitmap pages */
368+ /* Pin the next set of bitmap pages */
400369 return iova_bitmap_get (bitmap );
401370}
402371
@@ -416,17 +385,7 @@ static int iova_bitmap_advance(struct iova_bitmap *bitmap)
416385int iova_bitmap_for_each (struct iova_bitmap * bitmap , void * opaque ,
417386 iova_bitmap_fn_t fn )
418387{
419- int ret = 0 ;
420-
421- for (; !iova_bitmap_done (bitmap ) && !ret ;
422- ret = iova_bitmap_advance (bitmap )) {
423- ret = fn (bitmap , iova_bitmap_mapped_iova (bitmap ),
424- iova_bitmap_mapped_length (bitmap ), opaque );
425- if (ret )
426- break ;
427- }
428-
429- return ret ;
388+ return fn (bitmap , bitmap -> iova , bitmap -> length , opaque );
430389}
431390EXPORT_SYMBOL_NS_GPL (iova_bitmap_for_each , IOMMUFD );
432391
@@ -444,11 +403,25 @@ void iova_bitmap_set(struct iova_bitmap *bitmap,
444403 unsigned long iova , size_t length )
445404{
446405 struct iova_bitmap_map * mapped = & bitmap -> mapped ;
447- unsigned long cur_bit = ((iova - mapped -> iova ) >>
448- mapped -> pgshift ) + mapped -> pgoff * BITS_PER_BYTE ;
449- unsigned long last_bit = (((iova + length - 1 ) - mapped -> iova ) >>
450- mapped -> pgshift ) + mapped -> pgoff * BITS_PER_BYTE ;
451- unsigned long last_page_idx = mapped -> npages - 1 ;
406+ unsigned long cur_bit , last_bit , last_page_idx ;
407+
408+ update_indexes :
409+ if (unlikely (!iova_bitmap_mapped_range (mapped , iova , length ))) {
410+
411+ /*
412+ * The attempt to advance the base index to @iova
413+ * may fail if it's out of bounds, or pinning the pages
414+ * returns an error.
415+ */
416+ if (iova_bitmap_advance_to (bitmap , iova ))
417+ return ;
418+ }
419+
420+ last_page_idx = mapped -> npages - 1 ;
421+ cur_bit = ((iova - mapped -> iova ) >>
422+ mapped -> pgshift ) + mapped -> pgoff * BITS_PER_BYTE ;
423+ last_bit = (((iova + length - 1 ) - mapped -> iova ) >>
424+ mapped -> pgshift ) + mapped -> pgoff * BITS_PER_BYTE ;
452425
453426 do {
454427 unsigned int page_idx = cur_bit / BITS_PER_PAGE ;
@@ -457,18 +430,19 @@ void iova_bitmap_set(struct iova_bitmap *bitmap,
457430 last_bit - cur_bit + 1 );
458431 void * kaddr ;
459432
460- if (unlikely (page_idx > last_page_idx ))
461- break ;
433+ if (unlikely (page_idx > last_page_idx )) {
434+ unsigned long left =
435+ ((last_bit - cur_bit + 1 ) << mapped -> pgshift );
436+
437+ iova += (length - left );
438+ length = left ;
439+ goto update_indexes ;
440+ }
462441
463442 kaddr = kmap_local_page (mapped -> pages [page_idx ]);
464443 bitmap_set (kaddr , offset , nbits );
465444 kunmap_local (kaddr );
466445 cur_bit += nbits ;
467446 } while (cur_bit <= last_bit );
468-
469- if (unlikely (cur_bit <= last_bit )) {
470- bitmap -> set_ahead_length =
471- ((last_bit - cur_bit + 1 ) << bitmap -> mapped .pgshift );
472- }
473447}
474448EXPORT_SYMBOL_NS_GPL (iova_bitmap_set , IOMMUFD );
0 commit comments