Skip to content

Commit 3c33066

Browse files
LeoBrasmpe
authored andcommitted
powerpc/kernel/iommu: Add new iommu_table_in_use() helper
Having a function to check if the iommu table has any allocation helps deciding if a tbl can be reset for using a new DMA window. It should be enough to replace all instances of !bitmap_empty(tbl...). iommu_table_in_use() skips reserved memory, so we don't need to worry about releasing it before testing. This causes iommu_table_release_pages() to become unnecessary, given it is only used to remove reserved memory for testing. Also, only allow storing reserved memory values in tbl if they are valid in the table, so there is no need to check it in the new helper. Signed-off-by: Leonardo Bras <[email protected]> Reviewed-by: Alexey Kardashevskiy <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 0c634ba commit 3c33066

File tree

2 files changed

+32
-30
lines changed

2 files changed

+32
-30
lines changed

arch/powerpc/include/asm/iommu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ extern int iommu_tce_table_put(struct iommu_table *tbl);
154154
*/
155155
extern struct iommu_table *iommu_init_table(struct iommu_table *tbl,
156156
int nid, unsigned long res_start, unsigned long res_end);
157+
bool iommu_table_in_use(struct iommu_table *tbl);
157158

158159
#define IOMMU_TABLE_GROUP_MAX_TABLES 2
159160

arch/powerpc/kernel/iommu.c

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -690,32 +690,24 @@ static void iommu_table_reserve_pages(struct iommu_table *tbl,
690690
if (tbl->it_offset == 0)
691691
set_bit(0, tbl->it_map);
692692

693-
tbl->it_reserved_start = res_start;
694-
tbl->it_reserved_end = res_end;
695-
696-
/* Check if res_start..res_end isn't empty and overlaps the table */
697-
if (res_start && res_end &&
698-
(tbl->it_offset + tbl->it_size < res_start ||
699-
res_end < tbl->it_offset))
700-
return;
693+
if (res_start < tbl->it_offset)
694+
res_start = tbl->it_offset;
701695

702-
for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
703-
set_bit(i - tbl->it_offset, tbl->it_map);
704-
}
696+
if (res_end > (tbl->it_offset + tbl->it_size))
697+
res_end = tbl->it_offset + tbl->it_size;
705698

706-
static void iommu_table_release_pages(struct iommu_table *tbl)
707-
{
708-
int i;
699+
/* Check if res_start..res_end is a valid range in the table */
700+
if (res_start >= res_end) {
701+
tbl->it_reserved_start = tbl->it_offset;
702+
tbl->it_reserved_end = tbl->it_offset;
703+
return;
704+
}
709705

710-
/*
711-
* In case we have reserved the first bit, we should not emit
712-
* the warning below.
713-
*/
714-
if (tbl->it_offset == 0)
715-
clear_bit(0, tbl->it_map);
706+
tbl->it_reserved_start = res_start;
707+
tbl->it_reserved_end = res_end;
716708

717709
for (i = tbl->it_reserved_start; i < tbl->it_reserved_end; ++i)
718-
clear_bit(i - tbl->it_offset, tbl->it_map);
710+
set_bit(i - tbl->it_offset, tbl->it_map);
719711
}
720712

721713
/*
@@ -779,6 +771,22 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid,
779771
return tbl;
780772
}
781773

774+
bool iommu_table_in_use(struct iommu_table *tbl)
775+
{
776+
unsigned long start = 0, end;
777+
778+
/* ignore reserved bit0 */
779+
if (tbl->it_offset == 0)
780+
start = 1;
781+
end = tbl->it_reserved_start - tbl->it_offset;
782+
if (find_next_bit(tbl->it_map, end, start) != end)
783+
return true;
784+
785+
start = tbl->it_reserved_end - tbl->it_offset;
786+
end = tbl->it_size;
787+
return find_next_bit(tbl->it_map, end, start) != end;
788+
}
789+
782790
static void iommu_table_free(struct kref *kref)
783791
{
784792
struct iommu_table *tbl;
@@ -795,10 +803,8 @@ static void iommu_table_free(struct kref *kref)
795803

796804
iommu_debugfs_del(tbl);
797805

798-
iommu_table_release_pages(tbl);
799-
800806
/* verify that table contains no entries */
801-
if (!bitmap_empty(tbl->it_map, tbl->it_size))
807+
if (iommu_table_in_use(tbl))
802808
pr_warn("%s: Unexpected TCEs\n", __func__);
803809

804810
/* free bitmap */
@@ -1099,14 +1105,9 @@ int iommu_take_ownership(struct iommu_table *tbl)
10991105
for (i = 0; i < tbl->nr_pools; i++)
11001106
spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
11011107

1102-
iommu_table_release_pages(tbl);
1103-
1104-
if (!bitmap_empty(tbl->it_map, tbl->it_size)) {
1108+
if (iommu_table_in_use(tbl)) {
11051109
pr_err("iommu_tce: it_map is not empty");
11061110
ret = -EBUSY;
1107-
/* Undo iommu_table_release_pages, i.e. restore bit#0, etc */
1108-
iommu_table_reserve_pages(tbl, tbl->it_reserved_start,
1109-
tbl->it_reserved_end);
11101111
} else {
11111112
memset(tbl->it_map, 0xff, sz);
11121113
}

0 commit comments

Comments
 (0)