blob: 23633c0fda4a6029260f88e25e571896a2a75444 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
FUJITA Tomonori0291df82008-02-04 22:28:07 -08002/*
3 * IOMMU helper functions for the free area management
4 */
5
Paul Gortmaker8bc3bcc2011-11-16 21:29:17 -05006#include <linux/export.h>
Akinobu Mitaa66022c2009-12-15 16:48:28 -08007#include <linux/bitmap.h>
Paul Gortmaker50af5ea2012-01-20 18:35:53 -05008#include <linux/bug.h>
FUJITA Tomonori0291df82008-02-04 22:28:07 -08009
FUJITA Tomonori37158632008-03-04 14:29:27 -080010int iommu_is_span_boundary(unsigned int index, unsigned int nr,
11 unsigned long shift,
12 unsigned long boundary_size)
FUJITA Tomonori0291df82008-02-04 22:28:07 -080013{
FUJITA Tomonori37158632008-03-04 14:29:27 -080014 BUG_ON(!is_power_of_2(boundary_size));
15
FUJITA Tomonori0291df82008-02-04 22:28:07 -080016 shift = (shift + index) & (boundary_size - 1);
17 return shift + nr > boundary_size;
18}
19
20unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
21 unsigned long start, unsigned int nr,
22 unsigned long shift, unsigned long boundary_size,
23 unsigned long align_mask)
24{
25 unsigned long index;
Akinobu Mitaa66022c2009-12-15 16:48:28 -080026
27 /* We don't want the last of the limit */
28 size -= 1;
FUJITA Tomonori0291df82008-02-04 22:28:07 -080029again:
Akinobu Mitaa66022c2009-12-15 16:48:28 -080030 index = bitmap_find_next_zero_area(map, size, start, nr, align_mask);
31 if (index < size) {
FUJITA Tomonori37158632008-03-04 14:29:27 -080032 if (iommu_is_span_boundary(index, nr, shift, boundary_size)) {
Sebastian Ottf003a1f2016-08-02 14:04:13 -070033 start = ALIGN(shift + index, boundary_size) - shift;
FUJITA Tomonori0291df82008-02-04 22:28:07 -080034 goto again;
35 }
Akinobu Mitaa66022c2009-12-15 16:48:28 -080036 bitmap_set(map, index, nr);
37 return index;
FUJITA Tomonori0291df82008-02-04 22:28:07 -080038 }
Akinobu Mitaa66022c2009-12-15 16:48:28 -080039 return -1;
FUJITA Tomonori0291df82008-02-04 22:28:07 -080040}
41EXPORT_SYMBOL(iommu_area_alloc);