Skip to content

Commit bb27947

Browse files
committed
iommu/amd: Implement timeout to flush unmap queues
In case the queue doesn't fill up, we flush the TLB at least 10ms after the unmap happened to make sure that the TLB is cleaned up. Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent b1516a1 commit bb27947

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

drivers/iommu/amd_iommu.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ struct flush_queue {
105105

106106
DEFINE_PER_CPU(struct flush_queue, flush_queue);
107107

108+
static atomic_t queue_timer_on;
109+
static struct timer_list queue_timer;
110+
108111
/*
109112
* Domain for untranslated devices - only allocated
110113
* if iommu=pt passed on kernel cmd line.
@@ -2151,6 +2154,24 @@ static void __queue_flush(struct flush_queue *queue)
21512154
queue->next = 0;
21522155
}
21532156

2157+
void queue_flush_timeout(unsigned long unsused)
2158+
{
2159+
int cpu;
2160+
2161+
atomic_set(&queue_timer_on, 0);
2162+
2163+
for_each_possible_cpu(cpu) {
2164+
struct flush_queue *queue;
2165+
unsigned long flags;
2166+
2167+
queue = per_cpu_ptr(&flush_queue, cpu);
2168+
spin_lock_irqsave(&queue->lock, flags);
2169+
if (queue->next > 0)
2170+
__queue_flush(queue);
2171+
spin_unlock_irqrestore(&queue->lock, flags);
2172+
}
2173+
}
2174+
21542175
static void queue_add(struct dma_ops_domain *dma_dom,
21552176
unsigned long address, unsigned long pages)
21562177
{
@@ -2176,6 +2197,10 @@ static void queue_add(struct dma_ops_domain *dma_dom,
21762197
entry->dma_dom = dma_dom;
21772198

21782199
spin_unlock_irqrestore(&queue->lock, flags);
2200+
2201+
if (atomic_cmpxchg(&queue_timer_on, 0, 1) == 0)
2202+
mod_timer(&queue_timer, jiffies + msecs_to_jiffies(10));
2203+
21792204
put_cpu_ptr(&flush_queue);
21802205
}
21812206

@@ -2634,6 +2659,9 @@ int __init amd_iommu_init_api(void)
26342659

26352660
int __init amd_iommu_init_dma_ops(void)
26362661
{
2662+
setup_timer(&queue_timer, queue_flush_timeout, 0);
2663+
atomic_set(&queue_timer_on, 0);
2664+
26372665
swiotlb = iommu_pass_through ? 1 : 0;
26382666
iommu_detected = 1;
26392667

0 commit comments

Comments
 (0)