~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to xen/drivers/passthrough/vtd/qinval.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2006, Intel Corporation.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms and conditions of the GNU General Public License,
 
6
 * version 2, as published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope it will be useful, but WITHOUT
 
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
10
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
11
 * more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along with
 
14
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
15
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 
16
 *
 
17
 * Copyright (C) Allen Kay <allen.m.kay@intel.com>
 
18
 * Copyright (C) Xiaohui Xin <xiaohui.xin@intel.com>
 
19
 */
 
20
 
 
21
 
 
22
#include <xen/sched.h>
 
23
#include <xen/iommu.h>
 
24
#include <xen/time.h>
 
25
#include <xen/pci.h>
 
26
#include <xen/pci_regs.h>
 
27
#include "iommu.h"
 
28
#include "dmar.h"
 
29
#include "vtd.h"
 
30
#include "extern.h"
 
31
 
 
32
static void print_qi_regs(struct iommu *iommu)
 
33
{
 
34
    u64 val;
 
35
 
 
36
    val = dmar_readq(iommu->reg, DMAR_IQA_REG);
 
37
    printk("DMAR_IQA_REG = %"PRIx64"\n", val);
 
38
 
 
39
    val = dmar_readq(iommu->reg, DMAR_IQH_REG);
 
40
    printk("DMAR_IQH_REG = %"PRIx64"\n", val);
 
41
 
 
42
    val = dmar_readq(iommu->reg, DMAR_IQT_REG);
 
43
    printk("DMAR_IQT_REG = %"PRIx64"\n", val);
 
44
}
 
45
 
 
46
static int qinval_next_index(struct iommu *iommu)
 
47
{
 
48
    u64 tail;
 
49
 
 
50
    tail = dmar_readq(iommu->reg, DMAR_IQT_REG);
 
51
    tail >>= QINVAL_INDEX_SHIFT;
 
52
 
 
53
    /* (tail+1 == head) indicates a full queue, wait for HW */
 
54
    while ( ( tail + 1 ) % QINVAL_ENTRY_NR ==
 
55
            ( dmar_readq(iommu->reg, DMAR_IQH_REG) >> QINVAL_INDEX_SHIFT ) )
 
56
        cpu_relax();
 
57
 
 
58
    return tail;
 
59
}
 
60
 
 
61
static int qinval_update_qtail(struct iommu *iommu, int index)
 
62
{
 
63
    u64 val;
 
64
 
 
65
    /* Need hold register lock when update tail */
 
66
    ASSERT( spin_is_locked(&iommu->register_lock) );
 
67
    val = (index + 1) % QINVAL_ENTRY_NR;
 
68
    dmar_writeq(iommu->reg, DMAR_IQT_REG, (val << QINVAL_INDEX_SHIFT));
 
69
    return 0;
 
70
}
 
71
 
 
72
static int gen_cc_inv_dsc(struct iommu *iommu, int index,
 
73
    u16 did, u16 source_id, u8 function_mask, u8 granu)
 
74
{
 
75
    unsigned long flags;
 
76
    struct qinval_entry *qinval_entry = NULL, *qinval_entries;
 
77
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
78
    u64 entry_base = qi_ctrl->qinval_maddr +
 
79
                 (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
 
80
 
 
81
    spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
 
82
    qinval_entries =
 
83
        (struct qinval_entry *)map_vtd_domain_page(entry_base);
 
84
    qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
 
85
    qinval_entry->q.cc_inv_dsc.lo.type = TYPE_INVAL_CONTEXT;
 
86
    qinval_entry->q.cc_inv_dsc.lo.granu = granu;
 
87
    qinval_entry->q.cc_inv_dsc.lo.res_1 = 0;
 
88
    qinval_entry->q.cc_inv_dsc.lo.did = did;
 
89
    qinval_entry->q.cc_inv_dsc.lo.sid = source_id;
 
90
    qinval_entry->q.cc_inv_dsc.lo.fm = function_mask;
 
91
    qinval_entry->q.cc_inv_dsc.lo.res_2 = 0;
 
92
    qinval_entry->q.cc_inv_dsc.hi.res = 0;
 
93
 
 
94
    unmap_vtd_domain_page(qinval_entries);
 
95
    spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
 
96
 
 
97
    return 0;
 
98
}
 
99
 
 
100
int queue_invalidate_context(struct iommu *iommu,
 
101
    u16 did, u16 source_id, u8 function_mask, u8 granu)
 
102
{
 
103
    int ret = -1;
 
104
    unsigned long flags;
 
105
    int index = -1;
 
106
 
 
107
    spin_lock_irqsave(&iommu->register_lock, flags);
 
108
    index = qinval_next_index(iommu);
 
109
    if ( index == -1 )
 
110
        return -EBUSY;
 
111
    ret = gen_cc_inv_dsc(iommu, index, did, source_id,
 
112
                         function_mask, granu);
 
113
    ret |= qinval_update_qtail(iommu, index);
 
114
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
115
    return ret;
 
116
}
 
117
 
 
118
static int gen_iotlb_inv_dsc(struct iommu *iommu, int index,
 
119
    u8 granu, u8 dr, u8 dw, u16 did, u8 am, u8 ih, u64 addr)
 
120
{
 
121
    unsigned long flags;
 
122
    struct qinval_entry *qinval_entry = NULL, *qinval_entries;
 
123
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
124
    u64 entry_base = qi_ctrl->qinval_maddr +
 
125
                 (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
 
126
 
 
127
    spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
 
128
 
 
129
    qinval_entries =
 
130
        (struct qinval_entry *)map_vtd_domain_page(entry_base);
 
131
    qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
 
132
    qinval_entry->q.iotlb_inv_dsc.lo.type = TYPE_INVAL_IOTLB;
 
133
    qinval_entry->q.iotlb_inv_dsc.lo.granu = granu;
 
134
    qinval_entry->q.iotlb_inv_dsc.lo.dr = dr;
 
135
    qinval_entry->q.iotlb_inv_dsc.lo.dw = dw;
 
136
    qinval_entry->q.iotlb_inv_dsc.lo.res_1 = 0;
 
137
    qinval_entry->q.iotlb_inv_dsc.lo.did = did;
 
138
    qinval_entry->q.iotlb_inv_dsc.lo.res_2 = 0;
 
139
 
 
140
    qinval_entry->q.iotlb_inv_dsc.hi.am = am;
 
141
    qinval_entry->q.iotlb_inv_dsc.hi.ih = ih;
 
142
    qinval_entry->q.iotlb_inv_dsc.hi.res_1 = 0;
 
143
    qinval_entry->q.iotlb_inv_dsc.hi.addr = addr;
 
144
 
 
145
    unmap_vtd_domain_page(qinval_entries);
 
146
    spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
 
147
    return 0;
 
148
}
 
149
 
 
150
int queue_invalidate_iotlb(struct iommu *iommu,
 
151
    u8 granu, u8 dr, u8 dw, u16 did, u8 am, u8 ih, u64 addr)
 
152
{
 
153
    int ret = -1;
 
154
    unsigned long flags;
 
155
    int index = -1;
 
156
 
 
157
    spin_lock_irqsave(&iommu->register_lock, flags);
 
158
 
 
159
    index = qinval_next_index(iommu);
 
160
    if ( index == -1 )
 
161
        return -EBUSY;
 
162
    ret = gen_iotlb_inv_dsc(iommu, index, granu, dr, dw, did,
 
163
                            am, ih, addr);
 
164
    ret |= qinval_update_qtail(iommu, index);
 
165
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
166
    return ret;
 
167
}
 
168
 
 
169
static int gen_wait_dsc(struct iommu *iommu, int index,
 
170
    u8 iflag, u8 sw, u8 fn, u32 sdata, volatile u32 *saddr)
 
171
{
 
172
    unsigned long flags;
 
173
    struct qinval_entry *qinval_entry = NULL, *qinval_entries;
 
174
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
175
    u64 entry_base = qi_ctrl->qinval_maddr +
 
176
                 (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
 
177
 
 
178
    spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
 
179
    qinval_entries =
 
180
        (struct qinval_entry *)map_vtd_domain_page(entry_base);
 
181
    qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
 
182
    qinval_entry->q.inv_wait_dsc.lo.type = TYPE_INVAL_WAIT;
 
183
    qinval_entry->q.inv_wait_dsc.lo.iflag = iflag;
 
184
    qinval_entry->q.inv_wait_dsc.lo.sw = sw;
 
185
    qinval_entry->q.inv_wait_dsc.lo.fn = fn;
 
186
    qinval_entry->q.inv_wait_dsc.lo.res_1 = 0;
 
187
    qinval_entry->q.inv_wait_dsc.lo.sdata = sdata;
 
188
    qinval_entry->q.inv_wait_dsc.hi.res_1 = 0;
 
189
    qinval_entry->q.inv_wait_dsc.hi.saddr = virt_to_maddr(saddr) >> 2;
 
190
    unmap_vtd_domain_page(qinval_entries);
 
191
    spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
 
192
    return 0;
 
193
}
 
194
 
 
195
static int queue_invalidate_wait(struct iommu *iommu,
 
196
    u8 iflag, u8 sw, u8 fn)
 
197
{
 
198
    s_time_t start_time;
 
199
    u32 poll_slot = QINVAL_STAT_INIT;
 
200
    int index = -1;
 
201
    int ret = -1;
 
202
    unsigned long flags;
 
203
 
 
204
    spin_lock_irqsave(&iommu->register_lock, flags);
 
205
    index = qinval_next_index(iommu);
 
206
    if ( index == -1 )
 
207
        return -EBUSY;
 
208
 
 
209
    ret = gen_wait_dsc(iommu, index, iflag, sw, fn, QINVAL_STAT_DONE, &poll_slot);
 
210
    ret |= qinval_update_qtail(iommu, index);
 
211
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
212
 
 
213
    /* Now we don't support interrupt method */
 
214
    if ( sw )
 
215
    {
 
216
        /* In case all wait descriptor writes to same addr with same data */
 
217
        start_time = NOW();
 
218
        while ( poll_slot != QINVAL_STAT_DONE )
 
219
        {
 
220
            if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )
 
221
            {
 
222
                print_qi_regs(iommu);
 
223
                panic("queue invalidate wait descriptor was not executed\n");
 
224
            }
 
225
            cpu_relax();
 
226
        }
 
227
    }
 
228
    return ret;
 
229
}
 
230
 
 
231
int invalidate_sync(struct iommu *iommu)
 
232
{
 
233
    int ret = -1;
 
234
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
235
 
 
236
    if ( qi_ctrl->qinval_maddr != 0 )
 
237
    {
 
238
        ret = queue_invalidate_wait(iommu, 0, 1, 1);
 
239
        return ret;
 
240
    }
 
241
    return 0;
 
242
}
 
243
 
 
244
static int gen_dev_iotlb_inv_dsc(struct iommu *iommu, int index,
 
245
    u32 max_invs_pend, u16 sid, u16 size, u64 addr)
 
246
{
 
247
    unsigned long flags;
 
248
    struct qinval_entry *qinval_entry = NULL, *qinval_entries;
 
249
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
250
    u64 entry_base = qi_ctrl->qinval_maddr +
 
251
                 (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
 
252
 
 
253
    spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
 
254
 
 
255
    qinval_entries =
 
256
        (struct qinval_entry *)map_vtd_domain_page(entry_base);
 
257
    qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
 
258
    qinval_entry->q.dev_iotlb_inv_dsc.lo.type = TYPE_INVAL_DEVICE_IOTLB;
 
259
    qinval_entry->q.dev_iotlb_inv_dsc.lo.res_1 = 0;
 
260
    qinval_entry->q.dev_iotlb_inv_dsc.lo.max_invs_pend = max_invs_pend;
 
261
    qinval_entry->q.dev_iotlb_inv_dsc.lo.res_2 = 0;
 
262
    qinval_entry->q.dev_iotlb_inv_dsc.lo.sid = sid;
 
263
    qinval_entry->q.dev_iotlb_inv_dsc.lo.res_3 = 0;
 
264
 
 
265
    qinval_entry->q.dev_iotlb_inv_dsc.hi.size = size;
 
266
    qinval_entry->q.dev_iotlb_inv_dsc.hi.res_1 = 0;
 
267
    qinval_entry->q.dev_iotlb_inv_dsc.hi.addr = addr >> PAGE_SHIFT_4K;
 
268
 
 
269
    unmap_vtd_domain_page(qinval_entries);
 
270
    spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
 
271
    return 0;
 
272
}
 
273
 
 
274
int qinval_device_iotlb(struct iommu *iommu,
 
275
    u32 max_invs_pend, u16 sid, u16 size, u64 addr)
 
276
{
 
277
    int ret = -1;
 
278
    unsigned long flags;
 
279
    int index = -1;
 
280
 
 
281
    spin_lock_irqsave(&iommu->register_lock, flags);
 
282
    index = qinval_next_index(iommu);
 
283
    if ( index == -1 )
 
284
        return -EBUSY;
 
285
    ret = gen_dev_iotlb_inv_dsc(iommu, index, max_invs_pend,
 
286
                                sid, size, addr);
 
287
    ret |= qinval_update_qtail(iommu, index);
 
288
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
289
    return ret;
 
290
}
 
291
 
 
292
static int gen_iec_inv_dsc(struct iommu *iommu, int index,
 
293
    u8 granu, u8 im, u16 iidx)
 
294
{
 
295
    unsigned long flags;
 
296
    struct qinval_entry *qinval_entry = NULL, *qinval_entries;
 
297
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
298
    u64 entry_base = qi_ctrl->qinval_maddr +
 
299
                 (( index >> QINVAL_ENTRY_ORDER ) << PAGE_SHIFT );
 
300
 
 
301
    spin_lock_irqsave(&qi_ctrl->qinval_lock, flags);
 
302
 
 
303
    qinval_entries =
 
304
        (struct qinval_entry *)map_vtd_domain_page(entry_base);
 
305
    qinval_entry = &qinval_entries[index % (1 << QINVAL_ENTRY_ORDER)];
 
306
    qinval_entry->q.iec_inv_dsc.lo.type = TYPE_INVAL_IEC;
 
307
    qinval_entry->q.iec_inv_dsc.lo.granu = granu;
 
308
    qinval_entry->q.iec_inv_dsc.lo.res_1 = 0;
 
309
    qinval_entry->q.iec_inv_dsc.lo.im = im;
 
310
    qinval_entry->q.iec_inv_dsc.lo.iidx = iidx;
 
311
    qinval_entry->q.iec_inv_dsc.lo.res_2 = 0;
 
312
    qinval_entry->q.iec_inv_dsc.hi.res = 0;
 
313
 
 
314
    unmap_vtd_domain_page(qinval_entries);
 
315
    spin_unlock_irqrestore(&qi_ctrl->qinval_lock, flags);
 
316
    return 0;
 
317
}
 
318
 
 
319
int queue_invalidate_iec(struct iommu *iommu, u8 granu, u8 im, u16 iidx)
 
320
{
 
321
    int ret;
 
322
    unsigned long flags;
 
323
    int index = -1;
 
324
 
 
325
    spin_lock_irqsave(&iommu->register_lock, flags);
 
326
    index = qinval_next_index(iommu);
 
327
    if ( index == -1 )
 
328
        return -EBUSY;
 
329
    ret = gen_iec_inv_dsc(iommu, index, granu, im, iidx);
 
330
    ret |= qinval_update_qtail(iommu, index);
 
331
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
332
    return ret;
 
333
}
 
334
 
 
335
static int __iommu_flush_iec(struct iommu *iommu, u8 granu, u8 im, u16 iidx)
 
336
{
 
337
    int ret;
 
338
    ret = queue_invalidate_iec(iommu, granu, im, iidx);
 
339
    ret |= invalidate_sync(iommu);
 
340
 
 
341
    /*
 
342
     * reading vt-d architecture register will ensure
 
343
     * draining happens in implementation independent way.
 
344
     */
 
345
    (void)dmar_readq(iommu->reg, DMAR_CAP_REG);
 
346
    return ret;
 
347
}
 
348
 
 
349
int iommu_flush_iec_global(struct iommu *iommu)
 
350
{
 
351
    return __iommu_flush_iec(iommu, IEC_GLOBAL_INVL, 0, 0);
 
352
}
 
353
 
 
354
int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx)
 
355
{
 
356
   return __iommu_flush_iec(iommu, IEC_INDEX_INVL, im, iidx);
 
357
}
 
358
 
 
359
static int flush_context_qi(
 
360
    void *_iommu, u16 did, u16 sid, u8 fm, u64 type,
 
361
    int flush_non_present_entry)
 
362
{
 
363
    int ret = 0;
 
364
    struct iommu *iommu = (struct iommu *)_iommu;
 
365
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
366
 
 
367
    /*
 
368
     * In the non-present entry flush case, if hardware doesn't cache
 
369
     * non-present entry we do nothing and if hardware cache non-present
 
370
     * entry, we flush entries of domain 0 (the domain id is used to cache
 
371
     * any non-present entries)
 
372
     */
 
373
    if ( flush_non_present_entry )
 
374
    {
 
375
        if ( !cap_caching_mode(iommu->cap) )
 
376
            return 1;
 
377
        else
 
378
            did = 0;
 
379
    }
 
380
 
 
381
    if ( qi_ctrl->qinval_maddr != 0 )
 
382
    {
 
383
        ret = queue_invalidate_context(iommu, did, sid, fm,
 
384
                                       type >> DMA_CCMD_INVL_GRANU_OFFSET);
 
385
        ret |= invalidate_sync(iommu);
 
386
    }
 
387
    return ret;
 
388
}
 
389
 
 
390
static int flush_iotlb_qi(
 
391
    void *_iommu, u16 did,
 
392
    u64 addr, unsigned int size_order, u64 type,
 
393
    int flush_non_present_entry, int flush_dev_iotlb)
 
394
{
 
395
    u8 dr = 0, dw = 0;
 
396
    int ret = 0;
 
397
    struct iommu *iommu = (struct iommu *)_iommu;
 
398
    struct qi_ctrl *qi_ctrl = iommu_qi_ctrl(iommu);
 
399
 
 
400
    /*
 
401
     * In the non-present entry flush case, if hardware doesn't cache
 
402
     * non-present entry we do nothing and if hardware cache non-present
 
403
     * entry, we flush entries of domain 0 (the domain id is used to cache
 
404
     * any non-present entries)
 
405
     */
 
406
    if ( flush_non_present_entry )
 
407
    {
 
408
        if ( !cap_caching_mode(iommu->cap) )
 
409
            return 1;
 
410
        else
 
411
            did = 0;
 
412
    }
 
413
 
 
414
    if ( qi_ctrl->qinval_maddr != 0 )
 
415
    {
 
416
        /* use queued invalidation */
 
417
        if (cap_write_drain(iommu->cap))
 
418
            dw = 1;
 
419
        if (cap_read_drain(iommu->cap))
 
420
            dr = 1;
 
421
        /* Need to conside the ih bit later */
 
422
        ret = queue_invalidate_iotlb(iommu,
 
423
                  (type >> DMA_TLB_FLUSH_GRANU_OFFSET), dr,
 
424
                  dw, did, (u8)size_order, 0, addr);
 
425
        if ( flush_dev_iotlb )
 
426
            ret |= dev_invalidate_iotlb(iommu, did, addr, size_order, type);
 
427
        ret |= invalidate_sync(iommu);
 
428
    }
 
429
    return ret;
 
430
}
 
431
 
 
432
int enable_qinval(struct iommu *iommu)
 
433
{
 
434
    struct acpi_drhd_unit *drhd;
 
435
    struct qi_ctrl *qi_ctrl;
 
436
    struct iommu_flush *flush;
 
437
    u32 sts;
 
438
    unsigned long flags;
 
439
 
 
440
    qi_ctrl = iommu_qi_ctrl(iommu);
 
441
    flush = iommu_get_flush(iommu);
 
442
 
 
443
    ASSERT(ecap_queued_inval(iommu->ecap) && iommu_qinval);
 
444
 
 
445
    if ( qi_ctrl->qinval_maddr == 0 )
 
446
    {
 
447
        drhd = iommu_to_drhd(iommu);
 
448
        qi_ctrl->qinval_maddr = alloc_pgtable_maddr(drhd, QINVAL_ARCH_PAGE_NR);
 
449
        if ( qi_ctrl->qinval_maddr == 0 )
 
450
        {
 
451
            dprintk(XENLOG_WARNING VTDPREFIX,
 
452
                    "Cannot allocate memory for qi_ctrl->qinval_maddr\n");
 
453
            return -ENOMEM;
 
454
        }
 
455
    }
 
456
 
 
457
    flush->context = flush_context_qi;
 
458
    flush->iotlb = flush_iotlb_qi;
 
459
 
 
460
    /* Setup Invalidation Queue Address(IQA) register with the
 
461
     * address of the page we just allocated.  QS field at
 
462
     * bits[2:0] to indicate size of queue is one 4KB page.
 
463
     * That's 256 entries.  Queued Head (IQH) and Queue Tail (IQT)
 
464
     * registers are automatically reset to 0 with write
 
465
     * to IQA register.
 
466
     */
 
467
    qi_ctrl->qinval_maddr |= QINVAL_PAGE_ORDER;
 
468
 
 
469
    spin_lock_irqsave(&iommu->register_lock, flags);
 
470
    dmar_writeq(iommu->reg, DMAR_IQA_REG, qi_ctrl->qinval_maddr);
 
471
 
 
472
    dmar_writeq(iommu->reg, DMAR_IQT_REG, 0);
 
473
 
 
474
    /* enable queued invalidation hardware */
 
475
    sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
 
476
    dmar_writel(iommu->reg, DMAR_GCMD_REG, sts | DMA_GCMD_QIE);
 
477
 
 
478
    /* Make sure hardware complete it */
 
479
    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
 
480
                  (sts & DMA_GSTS_QIES), sts);
 
481
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
482
 
 
483
    return 0;
 
484
}
 
485
 
 
486
void disable_qinval(struct iommu *iommu)
 
487
{
 
488
    u32 sts;
 
489
    unsigned long flags;
 
490
 
 
491
    ASSERT(ecap_queued_inval(iommu->ecap) && iommu_qinval);
 
492
 
 
493
    spin_lock_irqsave(&iommu->register_lock, flags);
 
494
    sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
 
495
    dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_QIE));
 
496
 
 
497
    /* Make sure hardware complete it */
 
498
    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
 
499
                  !(sts & DMA_GSTS_QIES), sts);
 
500
    spin_unlock_irqrestore(&iommu->register_lock, flags);
 
501
}