Skip to content

Commit 821500d

Browse files
robclarkwilldeacon
authored andcommitted
iommu/io-pgtable-arm: Make pgtable walker more generic
We can re-use this basic pgtable walk logic in a few places. Signed-off-by: Rob Clark <[email protected]> Reviewed-by: Mostafa Saleh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 3e35c3e commit 821500d

File tree

1 file changed

+43
-24
lines changed

1 file changed

+43
-24
lines changed

drivers/iommu/io-pgtable-arm.c

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -741,33 +741,33 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
741741
}
742742

743743
struct io_pgtable_walk_data {
744-
struct iommu_dirty_bitmap *dirty;
744+
struct io_pgtable *iop;
745+
void *data;
746+
int (*visit)(struct io_pgtable_walk_data *walk_data, int lvl,
747+
arm_lpae_iopte *ptep, size_t size);
745748
unsigned long flags;
746749
u64 addr;
747750
const u64 end;
748751
};
749752

750-
static int __arm_lpae_iopte_walk_dirty(struct arm_lpae_io_pgtable *data,
751-
struct io_pgtable_walk_data *walk_data,
752-
arm_lpae_iopte *ptep,
753-
int lvl);
753+
static int __arm_lpae_iopte_walk(struct arm_lpae_io_pgtable *data,
754+
struct io_pgtable_walk_data *walk_data,
755+
arm_lpae_iopte *ptep,
756+
int lvl);
754757

755-
static int io_pgtable_visit_dirty(struct arm_lpae_io_pgtable *data,
756-
struct io_pgtable_walk_data *walk_data,
757-
arm_lpae_iopte *ptep, int lvl)
758+
static int io_pgtable_visit(struct arm_lpae_io_pgtable *data,
759+
struct io_pgtable_walk_data *walk_data,
760+
arm_lpae_iopte *ptep, int lvl)
758761
{
759762
struct io_pgtable *iop = &data->iop;
760763
arm_lpae_iopte pte = READ_ONCE(*ptep);
761764

762-
if (iopte_leaf(pte, lvl, iop->fmt)) {
763-
size_t size = ARM_LPAE_BLOCK_SIZE(lvl, data);
765+
size_t size = ARM_LPAE_BLOCK_SIZE(lvl, data);
766+
int ret = walk_data->visit(walk_data, lvl, ptep, size);
767+
if (ret)
768+
return ret;
764769

765-
if (iopte_writeable_dirty(pte)) {
766-
iommu_dirty_bitmap_record(walk_data->dirty,
767-
walk_data->addr, size);
768-
if (!(walk_data->flags & IOMMU_DIRTY_NO_CLEAR))
769-
iopte_set_writeable_clean(ptep);
770-
}
770+
if (iopte_leaf(pte, lvl, iop->fmt)) {
771771
walk_data->addr += size;
772772
return 0;
773773
}
@@ -776,13 +776,13 @@ static int io_pgtable_visit_dirty(struct arm_lpae_io_pgtable *data,
776776
return -EINVAL;
777777

778778
ptep = iopte_deref(pte, data);
779-
return __arm_lpae_iopte_walk_dirty(data, walk_data, ptep, lvl + 1);
779+
return __arm_lpae_iopte_walk(data, walk_data, ptep, lvl + 1);
780780
}
781781

782-
static int __arm_lpae_iopte_walk_dirty(struct arm_lpae_io_pgtable *data,
783-
struct io_pgtable_walk_data *walk_data,
784-
arm_lpae_iopte *ptep,
785-
int lvl)
782+
static int __arm_lpae_iopte_walk(struct arm_lpae_io_pgtable *data,
783+
struct io_pgtable_walk_data *walk_data,
784+
arm_lpae_iopte *ptep,
785+
int lvl)
786786
{
787787
u32 idx;
788788
int max_entries, ret;
@@ -797,14 +797,31 @@ static int __arm_lpae_iopte_walk_dirty(struct arm_lpae_io_pgtable *data,
797797

798798
for (idx = ARM_LPAE_LVL_IDX(walk_data->addr, lvl, data);
799799
(idx < max_entries) && (walk_data->addr < walk_data->end); ++idx) {
800-
ret = io_pgtable_visit_dirty(data, walk_data, ptep + idx, lvl);
800+
ret = io_pgtable_visit(data, walk_data, ptep + idx, lvl);
801801
if (ret)
802802
return ret;
803803
}
804804

805805
return 0;
806806
}
807807

808+
static int visit_dirty(struct io_pgtable_walk_data *walk_data, int lvl,
809+
arm_lpae_iopte *ptep, size_t size)
810+
{
811+
struct iommu_dirty_bitmap *dirty = walk_data->data;
812+
813+
if (!iopte_leaf(*ptep, lvl, walk_data->iop->fmt))
814+
return 0;
815+
816+
if (iopte_writeable_dirty(*ptep)) {
817+
iommu_dirty_bitmap_record(dirty, walk_data->addr, size);
818+
if (!(walk_data->flags & IOMMU_DIRTY_NO_CLEAR))
819+
iopte_set_writeable_clean(ptep);
820+
}
821+
822+
return 0;
823+
}
824+
808825
static int arm_lpae_read_and_clear_dirty(struct io_pgtable_ops *ops,
809826
unsigned long iova, size_t size,
810827
unsigned long flags,
@@ -813,7 +830,9 @@ static int arm_lpae_read_and_clear_dirty(struct io_pgtable_ops *ops,
813830
struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
814831
struct io_pgtable_cfg *cfg = &data->iop.cfg;
815832
struct io_pgtable_walk_data walk_data = {
816-
.dirty = dirty,
833+
.iop = &data->iop,
834+
.data = dirty,
835+
.visit = visit_dirty,
817836
.flags = flags,
818837
.addr = iova,
819838
.end = iova + size,
@@ -828,7 +847,7 @@ static int arm_lpae_read_and_clear_dirty(struct io_pgtable_ops *ops,
828847
if (data->iop.fmt != ARM_64_LPAE_S1)
829848
return -EINVAL;
830849

831-
return __arm_lpae_iopte_walk_dirty(data, &walk_data, ptep, lvl);
850+
return __arm_lpae_iopte_walk(data, &walk_data, ptep, lvl);
832851
}
833852

834853
static void arm_lpae_restrict_pgsizes(struct io_pgtable_cfg *cfg)

0 commit comments

Comments
 (0)