11
11
#include <linux/smp.h>
12
12
#include <linux/bitops.h>
13
13
#include <linux/cpu.h>
14
+ #include <linux/workqueue.h>
14
15
15
16
/* The anchor node sits above the top of the usable address space */
16
17
#define IOVA_ANCHOR ~0UL
@@ -627,6 +628,8 @@ EXPORT_SYMBOL_GPL(reserve_iova);
627
628
*/
628
629
#define IOVA_MAG_SIZE 127
629
630
631
+ #define IOVA_DEPOT_DELAY msecs_to_jiffies(100)
632
+
630
633
struct iova_magazine {
631
634
union {
632
635
unsigned long size ;
@@ -644,8 +647,11 @@ struct iova_cpu_rcache {
644
647
645
648
struct iova_rcache {
646
649
spinlock_t lock ;
650
+ unsigned int depot_size ;
647
651
struct iova_magazine * depot ;
648
652
struct iova_cpu_rcache __percpu * cpu_rcaches ;
653
+ struct iova_domain * iovad ;
654
+ struct delayed_work work ;
649
655
};
650
656
651
657
static struct iova_magazine * iova_magazine_alloc (gfp_t flags )
@@ -726,13 +732,33 @@ static struct iova_magazine *iova_depot_pop(struct iova_rcache *rcache)
726
732
727
733
rcache -> depot = mag -> next ;
728
734
mag -> size = IOVA_MAG_SIZE ;
735
+ rcache -> depot_size -- ;
729
736
return mag ;
730
737
}
731
738
732
739
static void iova_depot_push (struct iova_rcache * rcache , struct iova_magazine * mag )
733
740
{
734
741
mag -> next = rcache -> depot ;
735
742
rcache -> depot = mag ;
743
+ rcache -> depot_size ++ ;
744
+ }
745
+
746
+ static void iova_depot_work_func (struct work_struct * work )
747
+ {
748
+ struct iova_rcache * rcache = container_of (work , typeof (* rcache ), work .work );
749
+ struct iova_magazine * mag = NULL ;
750
+ unsigned long flags ;
751
+
752
+ spin_lock_irqsave (& rcache -> lock , flags );
753
+ if (rcache -> depot_size > num_online_cpus ())
754
+ mag = iova_depot_pop (rcache );
755
+ spin_unlock_irqrestore (& rcache -> lock , flags );
756
+
757
+ if (mag ) {
758
+ iova_magazine_free_pfns (mag , rcache -> iovad );
759
+ iova_magazine_free (mag );
760
+ schedule_delayed_work (& rcache -> work , IOVA_DEPOT_DELAY );
761
+ }
736
762
}
737
763
738
764
int iova_domain_init_rcaches (struct iova_domain * iovad )
@@ -752,6 +778,8 @@ int iova_domain_init_rcaches(struct iova_domain *iovad)
752
778
753
779
rcache = & iovad -> rcaches [i ];
754
780
spin_lock_init (& rcache -> lock );
781
+ rcache -> iovad = iovad ;
782
+ INIT_DELAYED_WORK (& rcache -> work , iova_depot_work_func );
755
783
rcache -> cpu_rcaches = __alloc_percpu (sizeof (* cpu_rcache ),
756
784
cache_line_size ());
757
785
if (!rcache -> cpu_rcaches ) {
@@ -812,6 +840,7 @@ static bool __iova_rcache_insert(struct iova_domain *iovad,
812
840
spin_lock (& rcache -> lock );
813
841
iova_depot_push (rcache , cpu_rcache -> loaded );
814
842
spin_unlock (& rcache -> lock );
843
+ schedule_delayed_work (& rcache -> work , IOVA_DEPOT_DELAY );
815
844
816
845
cpu_rcache -> loaded = new_mag ;
817
846
can_insert = true;
@@ -912,6 +941,7 @@ static void free_iova_rcaches(struct iova_domain *iovad)
912
941
iova_magazine_free (cpu_rcache -> prev );
913
942
}
914
943
free_percpu (rcache -> cpu_rcaches );
944
+ cancel_delayed_work_sync (& rcache -> work );
915
945
while (rcache -> depot )
916
946
iova_magazine_free (iova_depot_pop (rcache ));
917
947
}
0 commit comments