@@ -74,87 +74,61 @@ static u64 *first_pte_l7(u64 *pte, unsigned long *page_size,
7474 *
7575 ****************************************************************************/
7676
77- static void free_page_list ( struct page * freelist )
77+ static void free_pt_page ( u64 * pt , struct list_head * freelist )
7878{
79- while (freelist != NULL ) {
80- unsigned long p = (unsigned long )page_address (freelist );
79+ struct page * p = virt_to_page (pt );
8180
82- freelist = freelist -> freelist ;
83- free_page (p );
84- }
81+ list_add_tail (& p -> lru , freelist );
8582}
8683
87- static struct page * free_pt_page ( unsigned long pt , struct page * freelist )
84+ static void free_pt_lvl ( u64 * pt , struct list_head * freelist , int lvl )
8885{
89- struct page * p = virt_to_page ((void * )pt );
86+ u64 * p ;
87+ int i ;
9088
91- p -> freelist = freelist ;
89+ for (i = 0 ; i < 512 ; ++ i ) {
90+ /* PTE present? */
91+ if (!IOMMU_PTE_PRESENT (pt [i ]))
92+ continue ;
9293
93- return p ;
94- }
94+ /* Large PTE? */
95+ if (PM_PTE_LEVEL (pt [i ]) == 0 ||
96+ PM_PTE_LEVEL (pt [i ]) == 7 )
97+ continue ;
9598
96- #define DEFINE_FREE_PT_FN (LVL , FN ) \
97- static struct page *free_pt_##LVL (unsigned long __pt, struct page *freelist) \
98- { \
99- unsigned long p; \
100- u64 *pt; \
101- int i; \
102- \
103- pt = (u64 *)__pt; \
104- \
105- for (i = 0; i < 512; ++i) { \
106- /* PTE present? */ \
107- if (!IOMMU_PTE_PRESENT (pt [i ])) \
108- continue ; \
109- \
110- /* Large PTE? */ \
111- if (PM_PTE_LEVEL (pt [i ]) == 0 || \
112- PM_PTE_LEVEL (pt [i ]) == 7 ) \
113- continue ; \
114- \
115- p = (unsigned long )IOMMU_PTE_PAGE (pt [i ]); \
116- freelist = FN (p , freelist ); \
117- } \
118- \
119- return free_pt_page ((unsigned long )pt , freelist ); \
120- }
99+ /*
100+ * Free the next level. No need to look at l1 tables here since
101+ * they can only contain leaf PTEs; just free them directly.
102+ */
103+ p = IOMMU_PTE_PAGE (pt [i ]);
104+ if (lvl > 2 )
105+ free_pt_lvl (p , freelist , lvl - 1 );
106+ else
107+ free_pt_page (p , freelist );
108+ }
121109
122- DEFINE_FREE_PT_FN (l2 , free_pt_page )
123- DEFINE_FREE_PT_FN (l3 , free_pt_l2 )
124- DEFINE_FREE_PT_FN (l4 , free_pt_l3 )
125- DEFINE_FREE_PT_FN (l5 , free_pt_l4 )
126- DEFINE_FREE_PT_FN (l6 , free_pt_l5 )
110+ free_pt_page (pt , freelist );
111+ }
127112
128- static struct page * free_sub_pt (unsigned long root , int mode ,
129- struct page * freelist )
113+ static void free_sub_pt (u64 * root , int mode , struct list_head * freelist )
130114{
131115 switch (mode ) {
132116 case PAGE_MODE_NONE :
133117 case PAGE_MODE_7_LEVEL :
134118 break ;
135119 case PAGE_MODE_1_LEVEL :
136- freelist = free_pt_page (root , freelist );
120+ free_pt_page (root , freelist );
137121 break ;
138122 case PAGE_MODE_2_LEVEL :
139- freelist = free_pt_l2 (root , freelist );
140- break ;
141123 case PAGE_MODE_3_LEVEL :
142- freelist = free_pt_l3 (root , freelist );
143- break ;
144124 case PAGE_MODE_4_LEVEL :
145- freelist = free_pt_l4 (root , freelist );
146- break ;
147125 case PAGE_MODE_5_LEVEL :
148- freelist = free_pt_l5 (root , freelist );
149- break ;
150126 case PAGE_MODE_6_LEVEL :
151- freelist = free_pt_l6 (root , freelist );
127+ free_pt_lvl (root , freelist , mode );
152128 break ;
153129 default :
154130 BUG ();
155131 }
156-
157- return freelist ;
158132}
159133
160134void amd_iommu_domain_set_pgtable (struct protection_domain * domain ,
@@ -362,9 +336,9 @@ static u64 *fetch_pte(struct amd_io_pgtable *pgtable,
362336 return pte ;
363337}
364338
365- static struct page * free_clear_pte (u64 * pte , u64 pteval , struct page * freelist )
339+ static void free_clear_pte (u64 * pte , u64 pteval , struct list_head * freelist )
366340{
367- unsigned long pt ;
341+ u64 * pt ;
368342 int mode ;
369343
370344 while (cmpxchg64 (pte , pteval , 0 ) != pteval ) {
@@ -373,12 +347,12 @@ static struct page *free_clear_pte(u64 *pte, u64 pteval, struct page *freelist)
373347 }
374348
375349 if (!IOMMU_PTE_PRESENT (pteval ))
376- return freelist ;
350+ return ;
377351
378- pt = ( unsigned long ) IOMMU_PTE_PAGE (pteval );
352+ pt = IOMMU_PTE_PAGE (pteval );
379353 mode = IOMMU_PTE_MODE (pteval );
380354
381- return free_sub_pt (pt , mode , freelist );
355+ free_sub_pt (pt , mode , freelist );
382356}
383357
384358/*
@@ -392,7 +366,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
392366 phys_addr_t paddr , size_t size , int prot , gfp_t gfp )
393367{
394368 struct protection_domain * dom = io_pgtable_ops_to_domain (ops );
395- struct page * freelist = NULL ;
369+ LIST_HEAD ( freelist ) ;
396370 bool updated = false;
397371 u64 __pte , * pte ;
398372 int ret , i , count ;
@@ -412,9 +386,9 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
412386 goto out ;
413387
414388 for (i = 0 ; i < count ; ++ i )
415- freelist = free_clear_pte (& pte [i ], pte [i ], freelist );
389+ free_clear_pte (& pte [i ], pte [i ], & freelist );
416390
417- if (freelist != NULL )
391+ if (! list_empty ( & freelist ) )
418392 updated = true;
419393
420394 if (count > 1 ) {
@@ -449,7 +423,7 @@ static int iommu_v1_map_page(struct io_pgtable_ops *ops, unsigned long iova,
449423 }
450424
451425 /* Everything flushed out, free pages now */
452- free_page_list ( freelist );
426+ put_pages_list ( & freelist );
453427
454428 return ret ;
455429}
@@ -511,8 +485,7 @@ static void v1_free_pgtable(struct io_pgtable *iop)
511485{
512486 struct amd_io_pgtable * pgtable = container_of (iop , struct amd_io_pgtable , iop );
513487 struct protection_domain * dom ;
514- struct page * freelist = NULL ;
515- unsigned long root ;
488+ LIST_HEAD (freelist );
516489
517490 if (pgtable -> mode == PAGE_MODE_NONE )
518491 return ;
@@ -529,10 +502,9 @@ static void v1_free_pgtable(struct io_pgtable *iop)
529502 BUG_ON (pgtable -> mode < PAGE_MODE_NONE ||
530503 pgtable -> mode > PAGE_MODE_6_LEVEL );
531504
532- root = (unsigned long )pgtable -> root ;
533- freelist = free_sub_pt (root , pgtable -> mode , freelist );
505+ free_sub_pt (pgtable -> root , pgtable -> mode , & freelist );
534506
535- free_page_list ( freelist );
507+ put_pages_list ( & freelist );
536508}
537509
538510static struct io_pgtable * v1_alloc_pgtable (struct io_pgtable_cfg * cfg , void * cookie )
0 commit comments