- disable pci resize on 32-bit systems (Nirmoy)
- don't leak the ccs state (Matt) - TLB invalidation fixes (Chris) [now with all fixes of fixes] -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAmL1bnMACgkQ+mJfZA7r E8oQBAf+IHHvIp89jM/lwwnKZ4IwsD+kWGo4TnN57uHwzxMaIXKTlG9Em2HPhSgL PyvV86Q1SLv+fo59SCSOg2z0+m3gUZHdJ4IAjDkWUbluCoXvB+51NuYKtQjtZE7J zkR0dLzsT3Jo0gUc5IofkIA7m7U1y9TA3W+eWyJuBz4gIEXttu/YX/ZMJbATL7qT rDFFCEfTNDb/Zui8tNYwlPaVDWU/JxtU3LFpZgphcp42ancgXkf4J7mMA4Q3nXnz QBbMlk7urYz0LIj+ICrWutTa4SN7y3y7Z9pknivyxawTIzwk+RXTJ70+kDHe3dhK 3x0x4bk2uFpEo8y0mMzz4Bhn9i1zXA== =8hPH -----END PGP SIGNATURE----- Merge tag 'drm-intel-next-fixes-2022-08-11' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes - disable pci resize on 32-bit systems (Nirmoy) - don't leak the ccs state (Matt) - TLB invalidation fixes (Chris) [now with all fixes of fixes] Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/YvVumNCga+90fYN0@intel.com
This commit is contained in:
commit
8ae4be56dd
@ -268,7 +268,7 @@ static void __i915_gem_object_free_mmaps(struct drm_i915_gem_object *obj)
|
||||
*/
|
||||
void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
assert_object_held(obj);
|
||||
assert_object_held_shared(obj);
|
||||
|
||||
if (!list_empty(&obj->vma.list)) {
|
||||
struct i915_vma *vma;
|
||||
@ -331,15 +331,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!i915_gem_object_trylock(obj, NULL)) {
|
||||
/* busy, toss it back to the pile */
|
||||
if (llist_add(&obj->freed, &i915->mm.free_list))
|
||||
queue_delayed_work(i915->wq, &i915->mm.free_work, msecs_to_jiffies(10));
|
||||
continue;
|
||||
}
|
||||
|
||||
__i915_gem_object_pages_fini(obj);
|
||||
i915_gem_object_unlock(obj);
|
||||
__i915_gem_free_object(obj);
|
||||
|
||||
/* But keep the pointer alive for RCU-protected lookups */
|
||||
@ -359,7 +351,7 @@ void i915_gem_flush_free_objects(struct drm_i915_private *i915)
|
||||
static void __i915_gem_free_work(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *i915 =
|
||||
container_of(work, struct drm_i915_private, mm.free_work.work);
|
||||
container_of(work, struct drm_i915_private, mm.free_work);
|
||||
|
||||
i915_gem_flush_free_objects(i915);
|
||||
}
|
||||
@ -391,7 +383,7 @@ static void i915_gem_free_object(struct drm_gem_object *gem_obj)
|
||||
*/
|
||||
|
||||
if (llist_add(&obj->freed, &i915->mm.free_list))
|
||||
queue_delayed_work(i915->wq, &i915->mm.free_work, 0);
|
||||
queue_work(i915->wq, &i915->mm.free_work);
|
||||
}
|
||||
|
||||
void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
|
||||
@ -745,7 +737,7 @@ bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj)
|
||||
|
||||
void i915_gem_init__objects(struct drm_i915_private *i915)
|
||||
{
|
||||
INIT_DELAYED_WORK(&i915->mm.free_work, __i915_gem_free_work);
|
||||
INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
|
||||
}
|
||||
|
||||
void i915_objects_module_exit(void)
|
||||
|
@ -335,7 +335,6 @@ struct drm_i915_gem_object {
|
||||
#define I915_BO_READONLY BIT(7)
|
||||
#define I915_TILING_QUIRK_BIT 8 /* unknown swizzling; do not release! */
|
||||
#define I915_BO_PROTECTED BIT(9)
|
||||
#define I915_BO_WAS_BOUND_BIT 10
|
||||
/**
|
||||
* @mem_flags - Mutable placement-related flags
|
||||
*
|
||||
@ -616,6 +615,8 @@ struct drm_i915_gem_object {
|
||||
* pages were last acquired.
|
||||
*/
|
||||
bool dirty:1;
|
||||
|
||||
u32 tlb;
|
||||
} mm;
|
||||
|
||||
struct {
|
||||
|
@ -6,14 +6,15 @@
|
||||
|
||||
#include <drm/drm_cache.h>
|
||||
|
||||
#include "gt/intel_gt.h"
|
||||
#include "gt/intel_gt_pm.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem_object.h"
|
||||
#include "i915_scatterlist.h"
|
||||
#include "i915_gem_lmem.h"
|
||||
#include "i915_gem_mman.h"
|
||||
|
||||
#include "gt/intel_gt.h"
|
||||
|
||||
void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
|
||||
struct sg_table *pages,
|
||||
unsigned int sg_page_sizes)
|
||||
@ -190,6 +191,18 @@ static void unmap_object(struct drm_i915_gem_object *obj, void *ptr)
|
||||
vunmap(ptr);
|
||||
}
|
||||
|
||||
static void flush_tlb_invalidate(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||
struct intel_gt *gt = to_gt(i915);
|
||||
|
||||
if (!obj->mm.tlb)
|
||||
return;
|
||||
|
||||
intel_gt_invalidate_tlb(gt, obj->mm.tlb);
|
||||
obj->mm.tlb = 0;
|
||||
}
|
||||
|
||||
struct sg_table *
|
||||
__i915_gem_object_unset_pages(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
@ -215,13 +228,7 @@ __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj)
|
||||
__i915_gem_object_reset_page_iter(obj);
|
||||
obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0;
|
||||
|
||||
if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) {
|
||||
struct drm_i915_private *i915 = to_i915(obj->base.dev);
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
with_intel_runtime_pm_if_active(&i915->runtime_pm, wakeref)
|
||||
intel_gt_invalidate_tlbs(to_gt(i915));
|
||||
}
|
||||
flush_tlb_invalidate(obj);
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include "pxp/intel_pxp.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_perf_oa_regs.h"
|
||||
#include "intel_context.h"
|
||||
#include "intel_engine_pm.h"
|
||||
#include "intel_engine_regs.h"
|
||||
#include "intel_ggtt_gmch.h"
|
||||
#include "intel_gt.h"
|
||||
@ -36,8 +38,6 @@ static void __intel_gt_init_early(struct intel_gt *gt)
|
||||
{
|
||||
spin_lock_init(>->irq_lock);
|
||||
|
||||
mutex_init(>->tlb_invalidate_lock);
|
||||
|
||||
INIT_LIST_HEAD(>->closed_vma);
|
||||
spin_lock_init(>->closed_lock);
|
||||
|
||||
@ -48,6 +48,8 @@ static void __intel_gt_init_early(struct intel_gt *gt)
|
||||
intel_gt_init_reset(gt);
|
||||
intel_gt_init_requests(gt);
|
||||
intel_gt_init_timelines(gt);
|
||||
mutex_init(>->tlb.invalidate_lock);
|
||||
seqcount_mutex_init(>->tlb.seqno, >->tlb.invalidate_lock);
|
||||
intel_gt_pm_init_early(gt);
|
||||
|
||||
intel_uc_init_early(>->uc);
|
||||
@ -768,6 +770,7 @@ void intel_gt_driver_late_release_all(struct drm_i915_private *i915)
|
||||
intel_gt_fini_requests(gt);
|
||||
intel_gt_fini_reset(gt);
|
||||
intel_gt_fini_timelines(gt);
|
||||
mutex_destroy(>->tlb.invalidate_lock);
|
||||
intel_engines_free(gt);
|
||||
}
|
||||
}
|
||||
@ -906,7 +909,7 @@ get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8,
|
||||
return rb;
|
||||
}
|
||||
|
||||
void intel_gt_invalidate_tlbs(struct intel_gt *gt)
|
||||
static void mmio_invalidate_full(struct intel_gt *gt)
|
||||
{
|
||||
static const i915_reg_t gen8_regs[] = {
|
||||
[RENDER_CLASS] = GEN8_RTCR,
|
||||
@ -924,13 +927,11 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt)
|
||||
struct drm_i915_private *i915 = gt->i915;
|
||||
struct intel_uncore *uncore = gt->uncore;
|
||||
struct intel_engine_cs *engine;
|
||||
intel_engine_mask_t awake, tmp;
|
||||
enum intel_engine_id id;
|
||||
const i915_reg_t *regs;
|
||||
unsigned int num = 0;
|
||||
|
||||
if (I915_SELFTEST_ONLY(gt->awake == -ENODEV))
|
||||
return;
|
||||
|
||||
if (GRAPHICS_VER(i915) == 12) {
|
||||
regs = gen12_regs;
|
||||
num = ARRAY_SIZE(gen12_regs);
|
||||
@ -945,28 +946,41 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt)
|
||||
"Platform does not implement TLB invalidation!"))
|
||||
return;
|
||||
|
||||
GEM_TRACE("\n");
|
||||
|
||||
assert_rpm_wakelock_held(&i915->runtime_pm);
|
||||
|
||||
mutex_lock(>->tlb_invalidate_lock);
|
||||
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
|
||||
|
||||
spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */
|
||||
|
||||
awake = 0;
|
||||
for_each_engine(engine, gt, id) {
|
||||
struct reg_and_bit rb;
|
||||
|
||||
if (!intel_engine_pm_is_awake(engine))
|
||||
continue;
|
||||
|
||||
rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
|
||||
if (!i915_mmio_reg_offset(rb.reg))
|
||||
continue;
|
||||
|
||||
intel_uncore_write_fw(uncore, rb.reg, rb.bit);
|
||||
awake |= engine->mask;
|
||||
}
|
||||
|
||||
GT_TRACE(gt, "invalidated engines %08x\n", awake);
|
||||
|
||||
/* Wa_2207587034:tgl,dg1,rkl,adl-s,adl-p */
|
||||
if (awake &&
|
||||
(IS_TIGERLAKE(i915) ||
|
||||
IS_DG1(i915) ||
|
||||
IS_ROCKETLAKE(i915) ||
|
||||
IS_ALDERLAKE_S(i915) ||
|
||||
IS_ALDERLAKE_P(i915)))
|
||||
intel_uncore_write_fw(uncore, GEN12_OA_TLB_INV_CR, 1);
|
||||
|
||||
spin_unlock_irq(&uncore->lock);
|
||||
|
||||
for_each_engine(engine, gt, id) {
|
||||
for_each_engine_masked(engine, gt, awake, tmp) {
|
||||
struct reg_and_bit rb;
|
||||
|
||||
/*
|
||||
* HW architecture suggest typical invalidation time at 40us,
|
||||
* with pessimistic cases up to 100us and a recommendation to
|
||||
@ -974,12 +988,8 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt)
|
||||
*/
|
||||
const unsigned int timeout_us = 100;
|
||||
const unsigned int timeout_ms = 4;
|
||||
struct reg_and_bit rb;
|
||||
|
||||
rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
|
||||
if (!i915_mmio_reg_offset(rb.reg))
|
||||
continue;
|
||||
|
||||
if (__intel_wait_for_register_fw(uncore,
|
||||
rb.reg, rb.bit, 0,
|
||||
timeout_us, timeout_ms,
|
||||
@ -996,5 +1006,38 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt)
|
||||
* transitions.
|
||||
*/
|
||||
intel_uncore_forcewake_put_delayed(uncore, FORCEWAKE_ALL);
|
||||
mutex_unlock(>->tlb_invalidate_lock);
|
||||
}
|
||||
|
||||
static bool tlb_seqno_passed(const struct intel_gt *gt, u32 seqno)
|
||||
{
|
||||
u32 cur = intel_gt_tlb_seqno(gt);
|
||||
|
||||
/* Only skip if a *full* TLB invalidate barrier has passed */
|
||||
return (s32)(cur - ALIGN(seqno, 2)) > 0;
|
||||
}
|
||||
|
||||
void intel_gt_invalidate_tlb(struct intel_gt *gt, u32 seqno)
|
||||
{
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
if (I915_SELFTEST_ONLY(gt->awake == -ENODEV))
|
||||
return;
|
||||
|
||||
if (intel_gt_is_wedged(gt))
|
||||
return;
|
||||
|
||||
if (tlb_seqno_passed(gt, seqno))
|
||||
return;
|
||||
|
||||
with_intel_gt_pm_if_awake(gt, wakeref) {
|
||||
mutex_lock(>->tlb.invalidate_lock);
|
||||
if (tlb_seqno_passed(gt, seqno))
|
||||
goto unlock;
|
||||
|
||||
mmio_invalidate_full(gt);
|
||||
|
||||
write_seqcount_invalidate(>->tlb.seqno);
|
||||
unlock:
|
||||
mutex_unlock(>->tlb.invalidate_lock);
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,16 @@ void intel_gt_info_print(const struct intel_gt_info *info,
|
||||
|
||||
void intel_gt_watchdog_work(struct work_struct *work);
|
||||
|
||||
void intel_gt_invalidate_tlbs(struct intel_gt *gt);
|
||||
static inline u32 intel_gt_tlb_seqno(const struct intel_gt *gt)
|
||||
{
|
||||
return seqprop_sequence(>->tlb.seqno);
|
||||
}
|
||||
|
||||
static inline u32 intel_gt_next_invalidate_tlb_full(const struct intel_gt *gt)
|
||||
{
|
||||
return intel_gt_tlb_seqno(gt) | 1;
|
||||
}
|
||||
|
||||
void intel_gt_invalidate_tlb(struct intel_gt *gt, u32 seqno);
|
||||
|
||||
#endif /* __INTEL_GT_H__ */
|
||||
|
@ -55,6 +55,9 @@ static inline void intel_gt_pm_might_put(struct intel_gt *gt)
|
||||
for (tmp = 1, intel_gt_pm_get(gt); tmp; \
|
||||
intel_gt_pm_put(gt), tmp = 0)
|
||||
|
||||
#define with_intel_gt_pm_if_awake(gt, wf) \
|
||||
for (wf = intel_gt_pm_get_if_awake(gt); wf; intel_gt_pm_put_async(gt), wf = 0)
|
||||
|
||||
static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt)
|
||||
{
|
||||
return intel_wakeref_wait_for_idle(>->wakeref);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/llist.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/seqlock.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/workqueue.h>
|
||||
@ -83,7 +84,22 @@ struct intel_gt {
|
||||
struct intel_uc uc;
|
||||
struct intel_gsc gsc;
|
||||
|
||||
struct mutex tlb_invalidate_lock;
|
||||
struct {
|
||||
/* Serialize global tlb invalidations */
|
||||
struct mutex invalidate_lock;
|
||||
|
||||
/*
|
||||
* Batch TLB invalidations
|
||||
*
|
||||
* After unbinding the PTE, we need to ensure the TLB
|
||||
* are invalidated prior to releasing the physical pages.
|
||||
* But we only need one such invalidation for all unbinds,
|
||||
* so we track how many TLB invalidations have been
|
||||
* performed since unbind the PTE and only emit an extra
|
||||
* invalidate if no full barrier has been passed.
|
||||
*/
|
||||
seqcount_mutex_t seqno;
|
||||
} tlb;
|
||||
|
||||
struct i915_wa_list wa_list;
|
||||
|
||||
|
@ -708,7 +708,7 @@ intel_context_migrate_copy(struct intel_context *ce,
|
||||
u8 src_access, dst_access;
|
||||
struct i915_request *rq;
|
||||
int src_sz, dst_sz;
|
||||
bool ccs_is_src;
|
||||
bool ccs_is_src, overwrite_ccs;
|
||||
int err;
|
||||
|
||||
GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm);
|
||||
@ -749,6 +749,8 @@ intel_context_migrate_copy(struct intel_context *ce,
|
||||
get_ccs_sg_sgt(&it_ccs, bytes_to_cpy);
|
||||
}
|
||||
|
||||
overwrite_ccs = HAS_FLAT_CCS(i915) && !ccs_bytes_to_cpy && dst_is_lmem;
|
||||
|
||||
src_offset = 0;
|
||||
dst_offset = CHUNK_SZ;
|
||||
if (HAS_64K_PAGES(ce->engine->i915)) {
|
||||
@ -852,6 +854,25 @@ intel_context_migrate_copy(struct intel_context *ce,
|
||||
if (err)
|
||||
goto out_rq;
|
||||
ccs_bytes_to_cpy -= ccs_sz;
|
||||
} else if (overwrite_ccs) {
|
||||
err = rq->engine->emit_flush(rq, EMIT_INVALIDATE);
|
||||
if (err)
|
||||
goto out_rq;
|
||||
|
||||
/*
|
||||
* While we can't always restore/manage the CCS state,
|
||||
* we still need to ensure we don't leak the CCS state
|
||||
* from the previous user, so make sure we overwrite it
|
||||
* with something.
|
||||
*/
|
||||
err = emit_copy_ccs(rq, dst_offset, INDIRECT_ACCESS,
|
||||
dst_offset, DIRECT_ACCESS, len);
|
||||
if (err)
|
||||
goto out_rq;
|
||||
|
||||
err = rq->engine->emit_flush(rq, EMIT_INVALIDATE);
|
||||
if (err)
|
||||
goto out_rq;
|
||||
}
|
||||
|
||||
/* Arbitration is re-enabled between requests. */
|
||||
|
@ -206,8 +206,12 @@ void ppgtt_bind_vma(struct i915_address_space *vm,
|
||||
void ppgtt_unbind_vma(struct i915_address_space *vm,
|
||||
struct i915_vma_resource *vma_res)
|
||||
{
|
||||
if (vma_res->allocated)
|
||||
vm->clear_range(vm, vma_res->start, vma_res->vma_size);
|
||||
if (!vma_res->allocated)
|
||||
return;
|
||||
|
||||
vm->clear_range(vm, vma_res->start, vma_res->vma_size);
|
||||
if (vma_res->tlb)
|
||||
vma_invalidate_tlb(vm, vma_res->tlb);
|
||||
}
|
||||
|
||||
static unsigned long pd_count(u64 size, int shift)
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "gt/intel_gt_mcr.h"
|
||||
#include "gt/intel_gt_regs.h"
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
static void _release_bars(struct pci_dev *pdev)
|
||||
{
|
||||
int resno;
|
||||
@ -111,6 +112,9 @@ static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t
|
||||
pci_assign_unassigned_bus_resources(pdev->bus);
|
||||
pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd);
|
||||
}
|
||||
#else
|
||||
static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) {}
|
||||
#endif
|
||||
|
||||
static int
|
||||
region_lmem_release(struct intel_memory_region *mem)
|
||||
|
@ -247,7 +247,7 @@ struct i915_gem_mm {
|
||||
* List of objects which are pending destruction.
|
||||
*/
|
||||
struct llist_head free_list;
|
||||
struct delayed_work free_work;
|
||||
struct work_struct free_work;
|
||||
/**
|
||||
* Count of objects pending destructions. Used to skip needlessly
|
||||
* waiting on an RCU barrier if no objects are waiting to be freed.
|
||||
@ -1378,7 +1378,7 @@ static inline void i915_gem_drain_freed_objects(struct drm_i915_private *i915)
|
||||
* armed the work again.
|
||||
*/
|
||||
while (atomic_read(&i915->mm.free_count)) {
|
||||
flush_delayed_work(&i915->mm.free_work);
|
||||
flush_work(&i915->mm.free_work);
|
||||
flush_delayed_work(&i915->bdev.wq);
|
||||
rcu_barrier();
|
||||
}
|
||||
|
@ -538,8 +538,6 @@ int i915_vma_bind(struct i915_vma *vma,
|
||||
bind_flags);
|
||||
}
|
||||
|
||||
set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags);
|
||||
|
||||
atomic_or(bind_flags, &vma->flags);
|
||||
return 0;
|
||||
}
|
||||
@ -1310,6 +1308,19 @@ err_unpin:
|
||||
return err;
|
||||
}
|
||||
|
||||
void vma_invalidate_tlb(struct i915_address_space *vm, u32 *tlb)
|
||||
{
|
||||
/*
|
||||
* Before we release the pages that were bound by this vma, we
|
||||
* must invalidate all the TLBs that may still have a reference
|
||||
* back to our physical address. It only needs to be done once,
|
||||
* so after updating the PTE to point away from the pages, record
|
||||
* the most recent TLB invalidation seqno, and if we have not yet
|
||||
* flushed the TLBs upon release, perform a full invalidation.
|
||||
*/
|
||||
WRITE_ONCE(*tlb, intel_gt_next_invalidate_tlb_full(vm->gt));
|
||||
}
|
||||
|
||||
static void __vma_put_pages(struct i915_vma *vma, unsigned int count)
|
||||
{
|
||||
/* We allocate under vma_get_pages, so beware the shrinker */
|
||||
@ -1941,7 +1952,12 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async)
|
||||
vma->vm->skip_pte_rewrite;
|
||||
trace_i915_vma_unbind(vma);
|
||||
|
||||
unbind_fence = i915_vma_resource_unbind(vma_res);
|
||||
if (async)
|
||||
unbind_fence = i915_vma_resource_unbind(vma_res,
|
||||
&vma->obj->mm.tlb);
|
||||
else
|
||||
unbind_fence = i915_vma_resource_unbind(vma_res, NULL);
|
||||
|
||||
vma->resource = NULL;
|
||||
|
||||
atomic_and(~(I915_VMA_BIND_MASK | I915_VMA_ERROR | I915_VMA_GGTT_WRITE),
|
||||
@ -1949,10 +1965,13 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async)
|
||||
|
||||
i915_vma_detach(vma);
|
||||
|
||||
if (!async && unbind_fence) {
|
||||
dma_fence_wait(unbind_fence, false);
|
||||
dma_fence_put(unbind_fence);
|
||||
unbind_fence = NULL;
|
||||
if (!async) {
|
||||
if (unbind_fence) {
|
||||
dma_fence_wait(unbind_fence, false);
|
||||
dma_fence_put(unbind_fence);
|
||||
unbind_fence = NULL;
|
||||
}
|
||||
vma_invalidate_tlb(vma->vm, &vma->obj->mm.tlb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -213,6 +213,7 @@ bool i915_vma_misplaced(const struct i915_vma *vma,
|
||||
u64 size, u64 alignment, u64 flags);
|
||||
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
|
||||
void i915_vma_revoke_mmap(struct i915_vma *vma);
|
||||
void vma_invalidate_tlb(struct i915_address_space *vm, u32 *tlb);
|
||||
struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async);
|
||||
int __i915_vma_unbind(struct i915_vma *vma);
|
||||
int __must_check i915_vma_unbind(struct i915_vma *vma);
|
||||
|
@ -223,10 +223,13 @@ i915_vma_resource_fence_notify(struct i915_sw_fence *fence,
|
||||
* Return: A refcounted pointer to a dma-fence that signals when unbinding is
|
||||
* complete.
|
||||
*/
|
||||
struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res)
|
||||
struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res,
|
||||
u32 *tlb)
|
||||
{
|
||||
struct i915_address_space *vm = vma_res->vm;
|
||||
|
||||
vma_res->tlb = tlb;
|
||||
|
||||
/* Reference for the sw fence */
|
||||
i915_vma_resource_get(vma_res);
|
||||
|
||||
|
@ -67,6 +67,7 @@ struct i915_page_sizes {
|
||||
* taken when the unbind is scheduled.
|
||||
* @skip_pte_rewrite: During ggtt suspend and vm takedown pte rewriting
|
||||
* needs to be skipped for unbind.
|
||||
* @tlb: pointer for obj->mm.tlb, if async unbind. Otherwise, NULL
|
||||
*
|
||||
* The lifetime of a struct i915_vma_resource is from a binding request to
|
||||
* the actual possible asynchronous unbind has completed.
|
||||
@ -119,6 +120,8 @@ struct i915_vma_resource {
|
||||
bool immediate_unbind:1;
|
||||
bool needs_wakeref:1;
|
||||
bool skip_pte_rewrite:1;
|
||||
|
||||
u32 *tlb;
|
||||
};
|
||||
|
||||
bool i915_vma_resource_hold(struct i915_vma_resource *vma_res,
|
||||
@ -131,7 +134,8 @@ struct i915_vma_resource *i915_vma_resource_alloc(void);
|
||||
|
||||
void i915_vma_resource_free(struct i915_vma_resource *vma_res);
|
||||
|
||||
struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res);
|
||||
struct dma_fence *i915_vma_resource_unbind(struct i915_vma_resource *vma_res,
|
||||
u32 *tlb);
|
||||
|
||||
void __i915_vma_resource_init(struct i915_vma_resource *vma_res);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user