Skip to content

Commit a17e302

Browse files
rmurphy-armjoergroedel
authored andcommitted
iommu: Move flush queue data into iommu_dma_cookie
Complete the move into iommu-dma by refactoring the flush queues themselves to belong to the DMA cookie rather than the IOVA domain. The refactoring may as well extend to some minor cosmetic aspects too, to help us stay one step ahead of the style police. Signed-off-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/24304722005bc6f144e2a1fdd865d1465722fc2e.1639753638.git.robin.murphy@arm.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent f7f0748 commit a17e302

File tree

3 files changed

+95
-122
lines changed

3 files changed

+95
-122
lines changed

drivers/iommu/dma-iommu.c

Lines changed: 94 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
*/
1010

1111
#include <linux/acpi_iort.h>
12+
#include <linux/atomic.h>
13+
#include <linux/crash_dump.h>
1214
#include <linux/device.h>
13-
#include <linux/dma-map-ops.h>
15+
#include <linux/dma-direct.h>
1416
#include <linux/dma-iommu.h>
17+
#include <linux/dma-map-ops.h>
1518
#include <linux/gfp.h>
1619
#include <linux/huge_mm.h>
1720
#include <linux/iommu.h>
@@ -20,11 +23,10 @@
2023
#include <linux/mm.h>
2124
#include <linux/mutex.h>
2225
#include <linux/pci.h>
23-
#include <linux/swiotlb.h>
2426
#include <linux/scatterlist.h>
27+
#include <linux/spinlock.h>
28+
#include <linux/swiotlb.h>
2529
#include <linux/vmalloc.h>
26-
#include <linux/crash_dump.h>
27-
#include <linux/dma-direct.h>
2830

2931
struct iommu_dma_msi_page {
3032
struct list_head list;
@@ -41,7 +43,19 @@ struct iommu_dma_cookie {
4143
enum iommu_dma_cookie_type type;
4244
union {
4345
/* Full allocator for IOMMU_DMA_IOVA_COOKIE */
44-
struct iova_domain iovad;
46+
struct {
47+
struct iova_domain iovad;
48+
49+
struct iova_fq __percpu *fq; /* Flush queue */
50+
/* Number of TLB flushes that have been started */
51+
atomic64_t fq_flush_start_cnt;
52+
/* Number of TLB flushes that have been finished */
53+
atomic64_t fq_flush_finish_cnt;
54+
/* Timer to regularily empty the flush queues */
55+
struct timer_list fq_timer;
56+
/* 1 when timer is active, 0 when not */
57+
atomic_t fq_timer_on;
58+
};
4559
/* Trivial linear page allocator for IOMMU_DMA_MSI_COOKIE */
4660
dma_addr_t msi_iova;
4761
};
@@ -64,6 +78,27 @@ static int __init iommu_dma_forcedac_setup(char *str)
6478
}
6579
early_param("iommu.forcedac", iommu_dma_forcedac_setup);
6680

81+
/* Number of entries per flush queue */
82+
#define IOVA_FQ_SIZE 256
83+
84+
/* Timeout (in ms) after which entries are flushed from the queue */
85+
#define IOVA_FQ_TIMEOUT 10
86+
87+
/* Flush queue entry for deferred flushing */
88+
struct iova_fq_entry {
89+
unsigned long iova_pfn;
90+
unsigned long pages;
91+
struct list_head freelist;
92+
u64 counter; /* Flush counter when this entry was added */
93+
};
94+
95+
/* Per-CPU flush queue structure */
96+
struct iova_fq {
97+
struct iova_fq_entry entries[IOVA_FQ_SIZE];
98+
unsigned int head, tail;
99+
spinlock_t lock;
100+
};
101+
67102
#define fq_ring_for_each(i, fq) \
68103
for ((i) = (fq)->head; (i) != (fq)->tail; (i) = ((i) + 1) % IOVA_FQ_SIZE)
69104

@@ -73,9 +108,9 @@ static inline bool fq_full(struct iova_fq *fq)
73108
return (((fq->tail + 1) % IOVA_FQ_SIZE) == fq->head);
74109
}
75110

76-
static inline unsigned fq_ring_add(struct iova_fq *fq)
111+
static inline unsigned int fq_ring_add(struct iova_fq *fq)
77112
{
78-
unsigned idx = fq->tail;
113+
unsigned int idx = fq->tail;
79114

80115
assert_spin_locked(&fq->lock);
81116

@@ -84,10 +119,10 @@ static inline unsigned fq_ring_add(struct iova_fq *fq)
84119
return idx;
85120
}
86121

87-
static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
122+
static void fq_ring_free(struct iommu_dma_cookie *cookie, struct iova_fq *fq)
88123
{
89-
u64 counter = atomic64_read(&iovad->fq_flush_finish_cnt);
90-
unsigned idx;
124+
u64 counter = atomic64_read(&cookie->fq_flush_finish_cnt);
125+
unsigned int idx;
91126

92127
assert_spin_locked(&fq->lock);
93128

@@ -97,124 +132,125 @@ static void fq_ring_free(struct iova_domain *iovad, struct iova_fq *fq)
97132
break;
98133

99134
put_pages_list(&fq->entries[idx].freelist);
100-
free_iova_fast(iovad,
135+
free_iova_fast(&cookie->iovad,
101136
fq->entries[idx].iova_pfn,
102137
fq->entries[idx].pages);
103138

104139
fq->head = (fq->head + 1) % IOVA_FQ_SIZE;
105140
}
106141
}
107142

108-
static void iova_domain_flush(struct iova_domain *iovad)
143+
static void fq_flush_iotlb(struct iommu_dma_cookie *cookie)
109144
{
110-
atomic64_inc(&iovad->fq_flush_start_cnt);
111-
iovad->fq_domain->ops->flush_iotlb_all(iovad->fq_domain);
112-
atomic64_inc(&iovad->fq_flush_finish_cnt);
145+
atomic64_inc(&cookie->fq_flush_start_cnt);
146+
cookie->fq_domain->ops->flush_iotlb_all(cookie->fq_domain);
147+
atomic64_inc(&cookie->fq_flush_finish_cnt);
113148
}
114149

115150
static void fq_flush_timeout(struct timer_list *t)
116151
{
117-
struct iova_domain *iovad = from_timer(iovad, t, fq_timer);
152+
struct iommu_dma_cookie *cookie = from_timer(cookie, t, fq_timer);
118153
int cpu;
119154

120-
atomic_set(&iovad->fq_timer_on, 0);
121-
iova_domain_flush(iovad);
155+
atomic_set(&cookie->fq_timer_on, 0);
156+
fq_flush_iotlb(cookie);
122157

123158
for_each_possible_cpu(cpu) {
124159
unsigned long flags;
125160
struct iova_fq *fq;
126161

127-
fq = per_cpu_ptr(iovad->fq, cpu);
162+
fq = per_cpu_ptr(cookie->fq, cpu);
128163
spin_lock_irqsave(&fq->lock, flags);
129-
fq_ring_free(iovad, fq);
164+
fq_ring_free(cookie, fq);
130165
spin_unlock_irqrestore(&fq->lock, flags);
131166
}
132167
}
133168

134-
void queue_iova(struct iova_domain *iovad,
169+
static void queue_iova(struct iommu_dma_cookie *cookie,
135170
unsigned long pfn, unsigned long pages,
136171
struct list_head *freelist)
137172
{
138173
struct iova_fq *fq;
139174
unsigned long flags;
140-
unsigned idx;
175+
unsigned int idx;
141176

142177
/*
143178
* Order against the IOMMU driver's pagetable update from unmapping
144-
* @pte, to guarantee that iova_domain_flush() observes that if called
179+
* @pte, to guarantee that fq_flush_iotlb() observes that if called
145180
* from a different CPU before we release the lock below. Full barrier
146181
* so it also pairs with iommu_dma_init_fq() to avoid seeing partially
147182
* written fq state here.
148183
*/
149184
smp_mb();
150185

151-
fq = raw_cpu_ptr(iovad->fq);
186+
fq = raw_cpu_ptr(cookie->fq);
152187
spin_lock_irqsave(&fq->lock, flags);
153188

154189
/*
155190
* First remove all entries from the flush queue that have already been
156191
* flushed out on another CPU. This makes the fq_full() check below less
157192
* likely to be true.
158193
*/
159-
fq_ring_free(iovad, fq);
194+
fq_ring_free(cookie, fq);
160195

161196
if (fq_full(fq)) {
162-
iova_domain_flush(iovad);
163-
fq_ring_free(iovad, fq);
197+
fq_flush_iotlb(cookie);
198+
fq_ring_free(cookie, fq);
164199
}
165200

166201
idx = fq_ring_add(fq);
167202

168203
fq->entries[idx].iova_pfn = pfn;
169204
fq->entries[idx].pages = pages;
170-
fq->entries[idx].counter = atomic64_read(&iovad->fq_flush_start_cnt);
205+
fq->entries[idx].counter = atomic64_read(&cookie->fq_flush_start_cnt);
171206
list_splice(freelist, &fq->entries[idx].freelist);
172207

173208
spin_unlock_irqrestore(&fq->lock, flags);
174209

175210
/* Avoid false sharing as much as possible. */
176-
if (!atomic_read(&iovad->fq_timer_on) &&
177-
!atomic_xchg(&iovad->fq_timer_on, 1))
178-
mod_timer(&iovad->fq_timer,
211+
if (!atomic_read(&cookie->fq_timer_on) &&
212+
!atomic_xchg(&cookie->fq_timer_on, 1))
213+
mod_timer(&cookie->fq_timer,
179214
jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
180215
}
181216

182-
static void free_iova_flush_queue(struct iova_domain *iovad)
217+
static void iommu_dma_free_fq(struct iommu_dma_cookie *cookie)
183218
{
184219
int cpu, idx;
185220

186-
if (!iovad->fq)
221+
if (!cookie->fq)
187222
return;
188223

189-
del_timer_sync(&iovad->fq_timer);
190-
/*
191-
* This code runs when the iova_domain is being detroyed, so don't
192-
* bother to free iovas, just free any remaining pagetable pages.
193-
*/
224+
del_timer_sync(&cookie->fq_timer);
225+
/* The IOVAs will be torn down separately, so just free our queued pages */
194226
for_each_possible_cpu(cpu) {
195-
struct iova_fq *fq = per_cpu_ptr(iovad->fq, cpu);
227+
struct iova_fq *fq = per_cpu_ptr(cookie->fq, cpu);
196228

197229
fq_ring_for_each(idx, fq)
198230
put_pages_list(&fq->entries[idx].freelist);
199231
}
200232

201-
free_percpu(iovad->fq);
202-
203-
iovad->fq = NULL;
204-
iovad->fq_domain = NULL;
233+
free_percpu(cookie->fq);
205234
}
206235

207-
int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_domain)
236+
/* sysfs updates are serialised by the mutex of the group owning @domain */
237+
int iommu_dma_init_fq(struct iommu_domain *domain)
208238
{
239+
struct iommu_dma_cookie *cookie = domain->iova_cookie;
209240
struct iova_fq __percpu *queue;
210241
int i, cpu;
211242

212-
atomic64_set(&iovad->fq_flush_start_cnt, 0);
213-
atomic64_set(&iovad->fq_flush_finish_cnt, 0);
243+
if (cookie->fq_domain)
244+
return 0;
245+
246+
atomic64_set(&cookie->fq_flush_start_cnt, 0);
247+
atomic64_set(&cookie->fq_flush_finish_cnt, 0);
214248

215249
queue = alloc_percpu(struct iova_fq);
216-
if (!queue)
250+
if (!queue) {
251+
pr_warn("iova flush queue initialization failed\n");
217252
return -ENOMEM;
253+
}
218254

219255
for_each_possible_cpu(cpu) {
220256
struct iova_fq *fq = per_cpu_ptr(queue, cpu);
@@ -228,12 +264,16 @@ int init_iova_flush_queue(struct iova_domain *iovad, struct iommu_domain *fq_dom
228264
INIT_LIST_HEAD(&fq->entries[i].freelist);
229265
}
230266

231-
iovad->fq_domain = fq_domain;
232-
iovad->fq = queue;
233-
234-
timer_setup(&iovad->fq_timer, fq_flush_timeout, 0);
235-
atomic_set(&iovad->fq_timer_on, 0);
267+
cookie->fq = queue;
236268

269+
timer_setup(&cookie->fq_timer, fq_flush_timeout, 0);
270+
atomic_set(&cookie->fq_timer_on, 0);
271+
/*
272+
* Prevent incomplete fq state being observable. Pairs with path from
273+
* __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
274+
*/
275+
smp_wmb();
276+
WRITE_ONCE(cookie->fq_domain, domain);
237277
return 0;
238278
}
239279

@@ -318,7 +358,7 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
318358
return;
319359

320360
if (cookie->type == IOMMU_DMA_IOVA_COOKIE && cookie->iovad.granule) {
321-
free_iova_flush_queue(&cookie->iovad);
361+
iommu_dma_free_fq(cookie);
322362
put_iova_domain(&cookie->iovad);
323363
}
324364

@@ -467,29 +507,6 @@ static bool dev_use_swiotlb(struct device *dev)
467507
return IS_ENABLED(CONFIG_SWIOTLB) && dev_is_untrusted(dev);
468508
}
469509

470-
/* sysfs updates are serialised by the mutex of the group owning @domain */
471-
int iommu_dma_init_fq(struct iommu_domain *domain)
472-
{
473-
struct iommu_dma_cookie *cookie = domain->iova_cookie;
474-
int ret;
475-
476-
if (cookie->fq_domain)
477-
return 0;
478-
479-
ret = init_iova_flush_queue(&cookie->iovad, domain);
480-
if (ret) {
481-
pr_warn("iova flush queue initialization failed\n");
482-
return ret;
483-
}
484-
/*
485-
* Prevent incomplete iovad->fq being observable. Pairs with path from
486-
* __iommu_dma_unmap() through iommu_dma_free_iova() to queue_iova()
487-
*/
488-
smp_wmb();
489-
WRITE_ONCE(cookie->fq_domain, domain);
490-
return 0;
491-
}
492-
493510
/**
494511
* iommu_dma_init_domain - Initialise a DMA mapping domain
495512
* @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
@@ -620,7 +637,7 @@ static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
620637
if (cookie->type == IOMMU_DMA_MSI_COOKIE)
621638
cookie->msi_iova -= size;
622639
else if (gather && gather->queued)
623-
queue_iova(iovad, iova_pfn(iovad, iova),
640+
queue_iova(cookie, iova_pfn(iovad, iova),
624641
size >> iova_shift(iovad),
625642
&gather->freelist);
626643
else

drivers/iommu/iova.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
6161
iovad->start_pfn = start_pfn;
6262
iovad->dma_32bit_pfn = 1UL << (32 - iova_shift(iovad));
6363
iovad->max32_alloc_size = iovad->dma_32bit_pfn;
64-
iovad->fq_domain = NULL;
65-
iovad->fq = NULL;
6664
iovad->anchor.pfn_lo = iovad->anchor.pfn_hi = IOVA_ANCHOR;
6765
rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
6866
rb_insert_color(&iovad->anchor.node, &iovad->rbroot);

0 commit comments

Comments
 (0)