@@ -741,33 +741,33 @@ static phys_addr_t arm_lpae_iova_to_phys(struct io_pgtable_ops *ops,
741741}
742742
743743struct 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+
808825static 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
834853static void arm_lpae_restrict_pgsizes (struct io_pgtable_cfg * cfg )
0 commit comments