@@ -713,11 +713,11 @@ static struct i915_page_table *alloc_pt(struct i915_address_space *vm)
713713 return pt ;
714714}
715715
716- static struct i915_page_directory * __alloc_pd (void )
716+ static struct i915_page_directory * __alloc_pd (size_t sz )
717717{
718718 struct i915_page_directory * pd ;
719719
720- pd = kzalloc (sizeof ( * pd ) , I915_GFP_ALLOW_FAIL );
720+ pd = kzalloc (sz , I915_GFP_ALLOW_FAIL );
721721 if (unlikely (!pd ))
722722 return NULL ;
723723
@@ -729,7 +729,7 @@ static struct i915_page_directory *alloc_pd(struct i915_address_space *vm)
729729{
730730 struct i915_page_directory * pd ;
731731
732- pd = __alloc_pd ();
732+ pd = __alloc_pd (sizeof ( * pd ) );
733733 if (unlikely (!pd ))
734734 return ERR_PTR (- ENOMEM );
735735
@@ -766,7 +766,7 @@ __set_pd_entry(struct i915_page_directory * const pd,
766766 struct i915_page_dma * const to ,
767767 u64 (* encode )(const dma_addr_t , const enum i915_cache_level ))
768768{
769- GEM_BUG_ON (atomic_read (px_used (pd )) > 512 );
769+ GEM_BUG_ON (atomic_read (px_used (pd )) > ARRAY_SIZE ( pd -> entry ) );
770770
771771 atomic_inc (px_used (pd ));
772772 pd -> entry [idx ] = to ;
@@ -896,64 +896,34 @@ static inline unsigned int gen8_pt_count(u64 start, u64 end)
896896 return end - start ;
897897}
898898
899- static void gen8_free_page_tables (struct i915_address_space * vm ,
900- struct i915_page_directory * pd )
899+ static void __gen8_ppgtt_cleanup (struct i915_address_space * vm ,
900+ struct i915_page_directory * pd ,
901+ int count , int lvl )
901902{
902- int i ;
903-
904- for (i = 0 ; i < I915_PDES ; i ++ ) {
905- if (pd -> entry [i ])
906- free_pd (vm , pd -> entry [i ]);
907- }
908- }
909-
910- static void gen8_ppgtt_cleanup_3lvl (struct i915_address_space * vm ,
911- struct i915_page_directory * pdp )
912- {
913- const unsigned int pdpes = i915_pdpes_per_pdp (vm );
914- int i ;
915-
916- for (i = 0 ; i < pdpes ; i ++ ) {
917- if (!pdp -> entry [i ])
918- continue ;
919-
920- gen8_free_page_tables (vm , pdp -> entry [i ]);
921- free_pd (vm , pdp -> entry [i ]);
922- }
923-
924- free_px (vm , pdp );
925- }
926-
927- static void gen8_ppgtt_cleanup_4lvl (struct i915_ppgtt * ppgtt )
928- {
929- struct i915_page_directory * const pml4 = ppgtt -> pd ;
930- int i ;
931-
932- for (i = 0 ; i < GEN8_PML4ES_PER_PML4 ; i ++ ) {
933- struct i915_page_directory * pdp = i915_pdp_entry (pml4 , i );
903+ if (lvl ) {
904+ void * * pde = pd -> entry ;
934905
935- if (!pdp )
936- continue ;
906+ do {
907+ if (!* pde )
908+ continue ;
937909
938- gen8_ppgtt_cleanup_3lvl (& ppgtt -> vm , pdp );
910+ __gen8_ppgtt_cleanup (vm , * pde , GEN8_PDES , lvl - 1 );
911+ } while (pde ++ , -- count );
939912 }
940913
941- free_px (& ppgtt -> vm , pml4 );
914+ free_px (vm , pd );
942915}
943916
944917static void gen8_ppgtt_cleanup (struct i915_address_space * vm )
945918{
946- struct drm_i915_private * i915 = vm -> i915 ;
947919 struct i915_ppgtt * ppgtt = i915_vm_to_ppgtt (vm );
948920
949- if (intel_vgpu_active (i915 ))
921+ if (intel_vgpu_active (vm -> i915 ))
950922 gen8_ppgtt_notify_vgt (ppgtt , false);
951923
952- if (i915_vm_is_4lvl (vm ))
953- gen8_ppgtt_cleanup_4lvl (ppgtt );
954- else
955- gen8_ppgtt_cleanup_3lvl (& ppgtt -> vm , ppgtt -> pd );
956-
924+ __gen8_ppgtt_cleanup (vm , ppgtt -> pd ,
925+ vm -> total >> __gen8_pte_shift (vm -> top ),
926+ vm -> top );
957927 free_scratch (vm );
958928}
959929
@@ -1505,24 +1475,18 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
15051475 struct i915_page_directory * pdp = ppgtt -> pd ;
15061476 struct i915_page_directory * pd ;
15071477 u64 start = 0 , length = ppgtt -> vm .total ;
1508- u64 from = start ;
15091478 unsigned int pdpe ;
15101479
15111480 gen8_for_each_pdpe (pd , pdp , start , length , pdpe ) {
15121481 pd = alloc_pd (vm );
15131482 if (IS_ERR (pd ))
1514- goto unwind ;
1483+ return PTR_ERR ( pd ) ;
15151484
15161485 fill_px (pd , vm -> scratch [1 ].encode );
15171486 set_pd_entry (pdp , pdpe , pd );
15181487 }
15191488
15201489 return 0 ;
1521-
1522- unwind :
1523- gen8_ppgtt_clear_pdp (vm , pdp , from , start - from );
1524- atomic_set (px_used (pdp ), 0 );
1525- return - ENOMEM ;
15261490}
15271491
15281492static void ppgtt_init (struct i915_ppgtt * ppgtt , struct intel_gt * gt )
@@ -1550,9 +1514,14 @@ gen8_alloc_top_pd(struct i915_address_space *vm)
15501514
15511515 GEM_BUG_ON (count > ARRAY_SIZE (pd -> entry ));
15521516
1553- pd = alloc_pd (vm );
1554- if (IS_ERR (pd ))
1555- return pd ;
1517+ pd = __alloc_pd (offsetof(typeof (* pd ), entry [count ]));
1518+ if (unlikely (!pd ))
1519+ return ERR_PTR (- ENOMEM );
1520+
1521+ if (unlikely (setup_page_dma (vm , px_base (pd )))) {
1522+ kfree (pd );
1523+ return ERR_PTR (- ENOMEM );
1524+ }
15561525
15571526 fill_page_dma (px_base (pd ), vm -> scratch [vm -> top ].encode , count );
15581527 return pd ;
@@ -1625,7 +1594,9 @@ static struct i915_ppgtt *gen8_ppgtt_create(struct drm_i915_private *i915)
16251594 return ppgtt ;
16261595
16271596err_free_pd :
1628- free_px (& ppgtt -> vm , ppgtt -> pd );
1597+ __gen8_ppgtt_cleanup (& ppgtt -> vm , ppgtt -> pd ,
1598+ ppgtt -> vm .total >> __gen8_pte_shift (ppgtt -> vm .top ),
1599+ ppgtt -> vm .top );
16291600err_free_scratch :
16301601 free_scratch (& ppgtt -> vm );
16311602err_free :
@@ -2071,7 +2042,7 @@ static struct i915_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915)
20712042
20722043 ppgtt -> base .vm .pte_encode = ggtt -> vm .pte_encode ;
20732044
2074- ppgtt -> base .pd = __alloc_pd ();
2045+ ppgtt -> base .pd = __alloc_pd (sizeof ( * ppgtt -> base . pd ) );
20752046 if (!ppgtt -> base .pd ) {
20762047 err = - ENOMEM ;
20772048 goto err_free ;
0 commit comments