2016-11-11 17:43:54 +07:00
|
|
|
/*
|
|
|
|
* Copyright © 2016 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
* Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __I915_VMA_H__
|
|
|
|
#define __I915_VMA_H__
|
|
|
|
|
|
|
|
#include <linux/io-mapping.h>
|
2018-07-06 17:39:46 +07:00
|
|
|
#include <linux/rbtree.h>
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
#include <drm/drm_mm.h>
|
|
|
|
|
|
|
|
#include "i915_gem_gtt.h"
|
|
|
|
#include "i915_gem_fence_reg.h"
|
|
|
|
#include "i915_gem_object.h"
|
|
|
|
|
2019-02-05 20:00:02 +07:00
|
|
|
#include "i915_active.h"
|
2018-02-21 16:56:36 +07:00
|
|
|
#include "i915_request.h"
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
enum i915_cache_level;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A VMA represents a GEM BO that is bound into an address space. Therefore, a
|
|
|
|
* VMA's presence cannot be guaranteed before binding, or after unbinding the
|
|
|
|
* object into/from the address space.
|
|
|
|
*
|
|
|
|
* To make things as simple as possible (ie. no refcounting), a VMA's lifetime
|
|
|
|
* will always be <= an objects lifetime. So object refcounting should cover us.
|
|
|
|
*/
|
|
|
|
struct i915_vma {
|
|
|
|
struct drm_mm_node node;
|
|
|
|
struct drm_i915_gem_object *obj;
|
|
|
|
struct i915_address_space *vm;
|
2018-06-07 22:40:46 +07:00
|
|
|
const struct i915_vma_ops *ops;
|
2016-11-11 17:43:54 +07:00
|
|
|
struct drm_i915_fence_reg *fence;
|
2017-06-16 21:05:25 +07:00
|
|
|
struct reservation_object *resv; /** Alias of obj->resv */
|
2016-11-11 17:43:54 +07:00
|
|
|
struct sg_table *pages;
|
|
|
|
void __iomem *iomap;
|
2018-06-12 19:04:46 +07:00
|
|
|
void *private; /* owned by creator */
|
2016-11-11 17:43:54 +07:00
|
|
|
u64 size;
|
|
|
|
u64 display_alignment;
|
2017-10-07 05:18:20 +07:00
|
|
|
struct i915_page_sizes page_sizes;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2017-01-09 23:16:11 +07:00
|
|
|
u32 fence_size;
|
|
|
|
u32 fence_alignment;
|
|
|
|
|
2017-08-22 18:05:17 +07:00
|
|
|
/**
|
|
|
|
* Count of the number of times this vma has been opened by different
|
|
|
|
* handles (but same file) for execbuf, i.e. the number of aliases
|
|
|
|
* that exist in the ctx->handle_vmas LUT for this vma.
|
|
|
|
*/
|
|
|
|
unsigned int open_count;
|
2017-10-09 15:43:57 +07:00
|
|
|
unsigned long flags;
|
2016-11-11 17:43:54 +07:00
|
|
|
/**
|
drm/i915: Enlarge vma->pin_count
Previously we only accommodated having a vma pinned by a small number of
users, with the maximum being pinned for use by the display engine. As
such, we used a small bitfield only large enough to allow the vma to
be pinned twice (for back/front buffers) in each scanout plane. Keeping
the maximum permissible pin_count small allows us to quickly catch a
potential leak. However, as we want to split a 4096B page into 64
different cachelines and pin each cacheline for use by a different
timeline, we will exceed the current maximum permissible vma->pin_count
and so time has come to enlarge it.
Whilst we are here, try to pull together the similar bits:
Address/layout specification:
- bias, mappable, zone_4g: address limit specifiers
- fixed: address override, limits still apply though
- high: not strictly an address limit, but an address direction to search
Search controls:
- nonblock, nonfault, noevict
v2: Rewrite the guideline comment on bit consumption.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: John Harrison <john.C.Harrison@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190128181812.22804-2-chris@chris-wilson.co.uk
2019-01-29 01:18:08 +07:00
|
|
|
* How many users have pinned this object in GTT space.
|
2016-11-11 17:43:54 +07:00
|
|
|
*
|
drm/i915: Enlarge vma->pin_count
Previously we only accommodated having a vma pinned by a small number of
users, with the maximum being pinned for use by the display engine. As
such, we used a small bitfield only large enough to allow the vma to
be pinned twice (for back/front buffers) in each scanout plane. Keeping
the maximum permissible pin_count small allows us to quickly catch a
potential leak. However, as we want to split a 4096B page into 64
different cachelines and pin each cacheline for use by a different
timeline, we will exceed the current maximum permissible vma->pin_count
and so time has come to enlarge it.
Whilst we are here, try to pull together the similar bits:
Address/layout specification:
- bias, mappable, zone_4g: address limit specifiers
- fixed: address override, limits still apply though
- high: not strictly an address limit, but an address direction to search
Search controls:
- nonblock, nonfault, noevict
v2: Rewrite the guideline comment on bit consumption.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: John Harrison <john.C.Harrison@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190128181812.22804-2-chris@chris-wilson.co.uk
2019-01-29 01:18:08 +07:00
|
|
|
* This is a tightly bound, fairly small number of users, so we
|
|
|
|
* stuff inside the flags field so that we can both check for overflow
|
|
|
|
* and detect a no-op i915_vma_pin() in a single check, while also
|
|
|
|
* pinning the vma.
|
|
|
|
*
|
|
|
|
* The worst case display setup would have the same vma pinned for
|
|
|
|
* use on each plane on each crtc, while also building the next atomic
|
|
|
|
* state and holding a pin for the length of the cleanup queue. In the
|
|
|
|
* future, the flip queue may be increased from 1.
|
|
|
|
* Estimated worst case: 3 [qlen] * 4 [max crtcs] * 7 [max planes] = 84
|
|
|
|
*
|
|
|
|
* For GEM, the number of concurrent users for pwrite/pread is
|
|
|
|
* unbounded. For execbuffer, it is currently one but will in future
|
|
|
|
* be extended to allow multiple clients to pin vma concurrently.
|
|
|
|
*
|
|
|
|
* We also use suballocated pages, with each suballocation claiming
|
|
|
|
* its own pin on the shared vma. At present, this is limited to
|
|
|
|
* exclusive cachelines of a single page, so a maximum of 64 possible
|
|
|
|
* users.
|
2016-11-11 17:43:54 +07:00
|
|
|
*/
|
drm/i915: Enlarge vma->pin_count
Previously we only accommodated having a vma pinned by a small number of
users, with the maximum being pinned for use by the display engine. As
such, we used a small bitfield only large enough to allow the vma to
be pinned twice (for back/front buffers) in each scanout plane. Keeping
the maximum permissible pin_count small allows us to quickly catch a
potential leak. However, as we want to split a 4096B page into 64
different cachelines and pin each cacheline for use by a different
timeline, we will exceed the current maximum permissible vma->pin_count
and so time has come to enlarge it.
Whilst we are here, try to pull together the similar bits:
Address/layout specification:
- bias, mappable, zone_4g: address limit specifiers
- fixed: address override, limits still apply though
- high: not strictly an address limit, but an address direction to search
Search controls:
- nonblock, nonfault, noevict
v2: Rewrite the guideline comment on bit consumption.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: John Harrison <john.C.Harrison@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190128181812.22804-2-chris@chris-wilson.co.uk
2019-01-29 01:18:08 +07:00
|
|
|
#define I915_VMA_PIN_MASK 0xff
|
|
|
|
#define I915_VMA_PIN_OVERFLOW BIT(8)
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
/** Flags and address space this VMA is bound to */
|
drm/i915: Enlarge vma->pin_count
Previously we only accommodated having a vma pinned by a small number of
users, with the maximum being pinned for use by the display engine. As
such, we used a small bitfield only large enough to allow the vma to
be pinned twice (for back/front buffers) in each scanout plane. Keeping
the maximum permissible pin_count small allows us to quickly catch a
potential leak. However, as we want to split a 4096B page into 64
different cachelines and pin each cacheline for use by a different
timeline, we will exceed the current maximum permissible vma->pin_count
and so time has come to enlarge it.
Whilst we are here, try to pull together the similar bits:
Address/layout specification:
- bias, mappable, zone_4g: address limit specifiers
- fixed: address override, limits still apply though
- high: not strictly an address limit, but an address direction to search
Search controls:
- nonblock, nonfault, noevict
v2: Rewrite the guideline comment on bit consumption.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: John Harrison <john.C.Harrison@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190128181812.22804-2-chris@chris-wilson.co.uk
2019-01-29 01:18:08 +07:00
|
|
|
#define I915_VMA_GLOBAL_BIND BIT(9)
|
|
|
|
#define I915_VMA_LOCAL_BIND BIT(10)
|
2016-11-11 17:43:54 +07:00
|
|
|
#define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW)
|
|
|
|
|
drm/i915: Enlarge vma->pin_count
Previously we only accommodated having a vma pinned by a small number of
users, with the maximum being pinned for use by the display engine. As
such, we used a small bitfield only large enough to allow the vma to
be pinned twice (for back/front buffers) in each scanout plane. Keeping
the maximum permissible pin_count small allows us to quickly catch a
potential leak. However, as we want to split a 4096B page into 64
different cachelines and pin each cacheline for use by a different
timeline, we will exceed the current maximum permissible vma->pin_count
and so time has come to enlarge it.
Whilst we are here, try to pull together the similar bits:
Address/layout specification:
- bias, mappable, zone_4g: address limit specifiers
- fixed: address override, limits still apply though
- high: not strictly an address limit, but an address direction to search
Search controls:
- nonblock, nonfault, noevict
v2: Rewrite the guideline comment on bit consumption.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: John Harrison <john.C.Harrison@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190128181812.22804-2-chris@chris-wilson.co.uk
2019-01-29 01:18:08 +07:00
|
|
|
#define I915_VMA_GGTT BIT(11)
|
|
|
|
#define I915_VMA_CAN_FENCE BIT(12)
|
|
|
|
#define I915_VMA_CLOSED BIT(13)
|
|
|
|
#define I915_VMA_USERFAULT_BIT 14
|
2017-10-09 15:43:57 +07:00
|
|
|
#define I915_VMA_USERFAULT BIT(I915_VMA_USERFAULT_BIT)
|
drm/i915: Enlarge vma->pin_count
Previously we only accommodated having a vma pinned by a small number of
users, with the maximum being pinned for use by the display engine. As
such, we used a small bitfield only large enough to allow the vma to
be pinned twice (for back/front buffers) in each scanout plane. Keeping
the maximum permissible pin_count small allows us to quickly catch a
potential leak. However, as we want to split a 4096B page into 64
different cachelines and pin each cacheline for use by a different
timeline, we will exceed the current maximum permissible vma->pin_count
and so time has come to enlarge it.
Whilst we are here, try to pull together the similar bits:
Address/layout specification:
- bias, mappable, zone_4g: address limit specifiers
- fixed: address override, limits still apply though
- high: not strictly an address limit, but an address direction to search
Search controls:
- nonblock, nonfault, noevict
v2: Rewrite the guideline comment on bit consumption.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: John Harrison <john.C.Harrison@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190128181812.22804-2-chris@chris-wilson.co.uk
2019-01-29 01:18:08 +07:00
|
|
|
#define I915_VMA_GGTT_WRITE BIT(15)
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2019-02-05 20:00:02 +07:00
|
|
|
struct i915_active active;
|
drm/i915: Pull i915_gem_active into the i915_active family
Looking forward, we need to break the struct_mutex dependency on
i915_gem_active. In the meantime, external use of i915_gem_active is
quite beguiling, little do new users suspect that it implies a barrier
as each request it tracks must be ordered wrt the previous one. As one
of many, it can be used to track activity across multiple timelines, a
shared fence, which fits our unordered request submission much better. We
need to steer external users away from the singular, exclusive fence
imposed by i915_gem_active to i915_active instead. As part of that
process, we move i915_gem_active out of i915_request.c into
i915_active.c to start separating the two concepts, and rename it to
i915_active_request (both to tie it to the concept of tracking just one
request, and to give it a longer, less appealing name).
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190205130005.2807-5-chris@chris-wilson.co.uk
2019-02-05 20:00:05 +07:00
|
|
|
struct i915_active_request last_fence;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Support different GGTT views into the same object.
|
|
|
|
* This means there can be multiple VMA mappings per object and per VM.
|
|
|
|
* i915_ggtt_view_type is used to distinguish between those entries.
|
|
|
|
* The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also
|
|
|
|
* assumed in GEM functions which take no ggtt view parameter.
|
|
|
|
*/
|
|
|
|
struct i915_ggtt_view ggtt_view;
|
|
|
|
|
|
|
|
/** This object's place on the active/inactive lists */
|
|
|
|
struct list_head vm_link;
|
|
|
|
|
|
|
|
struct list_head obj_link; /* Link in the object's VMA list */
|
|
|
|
struct rb_node obj_node;
|
2017-06-16 21:05:16 +07:00
|
|
|
struct hlist_node obj_hash;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2017-06-15 15:14:35 +07:00
|
|
|
/** This vma's place in the execbuf reservation list */
|
|
|
|
struct list_head exec_link;
|
drm/i915: Eliminate lots of iterations over the execobjects array
The major scaling bottleneck in execbuffer is the processing of the
execobjects. Creating an auxiliary list is inefficient when compared to
using the execobject array we already have allocated.
Reservation is then split into phases. As we lookup up the VMA, we
try and bind it back into active location. Only if that fails, do we add
it to the unbound list for phase 2. In phase 2, we try and add all those
objects that could not fit into their previous location, with fallback
to retrying all objects and evicting the VM in case of severe
fragmentation. (This is the same as before, except that phase 1 is now
done inline with looking up the VMA to avoid an iteration over the
execobject array. In the ideal case, we eliminate the separate reservation
phase). During the reservation phase, we only evict from the VM between
passes (rather than currently as we try to fit every new VMA). In
testing with Unreal Engine's Atlantis demo which stresses the eviction
logic on gen7 class hardware, this speed up the framerate by a factor of
2.
The second loop amalgamation is between move_to_gpu and move_to_active.
As we always submit the request, even if incomplete, we can use the
current request to track active VMA as we perform the flushes and
synchronisation required.
The next big advancement is to avoid copying back to the user any
execobjects and relocations that are not changed.
v2: Add a Theory of Operation spiel.
v3: Fall back to slow relocations in preparation for flushing userptrs.
v4: Document struct members, factor out eb_validate_vma(), add a few
more comments to explain some magic and hide other magic behind macros.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
2017-06-16 21:05:19 +07:00
|
|
|
struct list_head reloc_link;
|
2017-06-15 15:14:35 +07:00
|
|
|
|
|
|
|
/** This vma's place in the eviction list */
|
|
|
|
struct list_head evict_link;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2018-05-04 02:51:14 +07:00
|
|
|
struct list_head closed_link;
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
/**
|
|
|
|
* Used for performing relocations during execbuffer insertion.
|
|
|
|
*/
|
2017-08-16 15:52:06 +07:00
|
|
|
unsigned int *exec_flags;
|
2017-06-16 21:05:25 +07:00
|
|
|
struct hlist_node exec_node;
|
2017-06-16 21:05:16 +07:00
|
|
|
u32 exec_handle;
|
2016-11-11 17:43:54 +07:00
|
|
|
};
|
|
|
|
|
2017-01-16 22:21:28 +07:00
|
|
|
struct i915_vma *
|
|
|
|
i915_vma_instance(struct drm_i915_gem_object *obj,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view);
|
|
|
|
|
2018-07-21 19:50:37 +07:00
|
|
|
void i915_vma_unpin_and_release(struct i915_vma **p_vma, unsigned int flags);
|
|
|
|
#define I915_VMA_RELEASE_MAP BIT(0)
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2019-02-05 20:00:02 +07:00
|
|
|
static inline bool i915_vma_is_active(const struct i915_vma *vma)
|
2018-07-06 17:39:46 +07:00
|
|
|
{
|
2019-02-05 20:00:02 +07:00
|
|
|
return !i915_active_is_idle(&vma->active);
|
2018-07-06 17:39:46 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
int __must_check i915_vma_move_to_active(struct i915_vma *vma,
|
|
|
|
struct i915_request *rq,
|
|
|
|
unsigned int flags);
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
static inline bool i915_vma_is_ggtt(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return vma->flags & I915_VMA_GGTT;
|
|
|
|
}
|
|
|
|
|
2017-12-06 19:49:14 +07:00
|
|
|
static inline bool i915_vma_has_ggtt_write(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return vma->flags & I915_VMA_GGTT_WRITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void i915_vma_set_ggtt_write(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(!i915_vma_is_ggtt(vma));
|
|
|
|
vma->flags |= I915_VMA_GGTT_WRITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void i915_vma_unset_ggtt_write(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
vma->flags &= ~I915_VMA_GGTT_WRITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void i915_vma_flush_writes(struct i915_vma *vma);
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return vma->flags & I915_VMA_CAN_FENCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool i915_vma_is_closed(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return vma->flags & I915_VMA_CLOSED;
|
|
|
|
}
|
|
|
|
|
2017-10-09 15:43:57 +07:00
|
|
|
static inline bool i915_vma_set_userfault(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma));
|
|
|
|
return __test_and_set_bit(I915_VMA_USERFAULT_BIT, &vma->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void i915_vma_unset_userfault(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return __clear_bit(I915_VMA_USERFAULT_BIT, &vma->flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool i915_vma_has_userfault(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return test_bit(I915_VMA_USERFAULT_BIT, &vma->flags);
|
|
|
|
}
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
static inline u32 i915_ggtt_offset(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(!i915_vma_is_ggtt(vma));
|
|
|
|
GEM_BUG_ON(!vma->node.allocated);
|
|
|
|
GEM_BUG_ON(upper_32_bits(vma->node.start));
|
|
|
|
GEM_BUG_ON(upper_32_bits(vma->node.start + vma->node.size - 1));
|
|
|
|
return lower_32_bits(vma->node.start);
|
|
|
|
}
|
|
|
|
|
2018-07-27 21:11:45 +07:00
|
|
|
static inline u32 i915_ggtt_pin_bias(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return i915_vm_to_ggtt(vma->vm)->pin_bias;
|
|
|
|
}
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
static inline struct i915_vma *i915_vma_get(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
i915_gem_object_get(vma->obj);
|
|
|
|
return vma;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void i915_vma_put(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
i915_gem_object_put(vma->obj);
|
|
|
|
}
|
|
|
|
|
2016-12-13 21:37:27 +07:00
|
|
|
static __always_inline ptrdiff_t ptrdiff(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
return a - b;
|
|
|
|
}
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
static inline long
|
|
|
|
i915_vma_compare(struct i915_vma *vma,
|
|
|
|
struct i915_address_space *vm,
|
|
|
|
const struct i915_ggtt_view *view)
|
|
|
|
{
|
2016-12-13 21:37:27 +07:00
|
|
|
ptrdiff_t cmp;
|
|
|
|
|
2016-11-04 03:08:52 +07:00
|
|
|
GEM_BUG_ON(view && !i915_is_ggtt(vm));
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2016-12-13 21:37:27 +07:00
|
|
|
cmp = ptrdiff(vma->vm, vm);
|
|
|
|
if (cmp)
|
|
|
|
return cmp;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2017-01-14 07:28:23 +07:00
|
|
|
BUILD_BUG_ON(I915_GGTT_VIEW_NORMAL != 0);
|
|
|
|
cmp = vma->ggtt_view.type;
|
2016-11-11 17:43:54 +07:00
|
|
|
if (!view)
|
2017-01-14 07:28:23 +07:00
|
|
|
return cmp;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2017-01-14 07:28:23 +07:00
|
|
|
cmp -= view->type;
|
|
|
|
if (cmp)
|
|
|
|
return cmp;
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2018-08-28 20:37:23 +07:00
|
|
|
assert_i915_gem_gtt_types();
|
|
|
|
|
2017-01-14 07:28:23 +07:00
|
|
|
/* ggtt_view.type also encodes its size so that we both distinguish
|
|
|
|
* different views using it as a "type" and also use a compact (no
|
|
|
|
* accessing of uninitialised padding bytes) memcmp without storing
|
|
|
|
* an extra parameter or adding more code.
|
2017-01-14 07:28:25 +07:00
|
|
|
*
|
|
|
|
* To ensure that the memcmp is valid for all branches of the union,
|
|
|
|
* even though the code looks like it is just comparing one branch,
|
|
|
|
* we assert above that all branches have the same address, and that
|
|
|
|
* each branch has a unique type/size.
|
2017-01-14 07:28:23 +07:00
|
|
|
*/
|
|
|
|
BUILD_BUG_ON(I915_GGTT_VIEW_NORMAL >= I915_GGTT_VIEW_PARTIAL);
|
|
|
|
BUILD_BUG_ON(I915_GGTT_VIEW_PARTIAL >= I915_GGTT_VIEW_ROTATED);
|
2017-01-14 07:28:25 +07:00
|
|
|
BUILD_BUG_ON(offsetof(typeof(*view), rotated) !=
|
|
|
|
offsetof(typeof(*view), partial));
|
|
|
|
return memcmp(&vma->ggtt_view.partial, &view->partial, view->type);
|
2016-11-11 17:43:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
|
|
|
|
u32 flags);
|
|
|
|
bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level);
|
2017-02-14 00:15:46 +07:00
|
|
|
bool i915_vma_misplaced(const struct i915_vma *vma,
|
|
|
|
u64 size, u64 alignment, u64 flags);
|
2016-11-11 17:43:54 +07:00
|
|
|
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
|
2017-10-09 15:43:57 +07:00
|
|
|
void i915_vma_revoke_mmap(struct i915_vma *vma);
|
2016-11-11 17:43:54 +07:00
|
|
|
int __must_check i915_vma_unbind(struct i915_vma *vma);
|
2017-06-16 21:05:16 +07:00
|
|
|
void i915_vma_unlink_ctx(struct i915_vma *vma);
|
2016-11-11 17:43:54 +07:00
|
|
|
void i915_vma_close(struct i915_vma *vma);
|
2018-05-04 02:51:14 +07:00
|
|
|
void i915_vma_reopen(struct i915_vma *vma);
|
|
|
|
void i915_vma_destroy(struct i915_vma *vma);
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
int __i915_vma_do_pin(struct i915_vma *vma,
|
|
|
|
u64 size, u64 alignment, u64 flags);
|
|
|
|
static inline int __must_check
|
|
|
|
i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
|
|
|
|
{
|
|
|
|
BUILD_BUG_ON(PIN_MBZ != I915_VMA_PIN_OVERFLOW);
|
|
|
|
BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND);
|
|
|
|
BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND);
|
|
|
|
|
|
|
|
/* Pin early to prevent the shrinker/eviction logic from destroying
|
|
|
|
* our vma as we insert and bind.
|
|
|
|
*/
|
2017-01-12 04:09:26 +07:00
|
|
|
if (likely(((++vma->flags ^ flags) & I915_VMA_BIND_MASK) == 0)) {
|
|
|
|
GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
|
|
|
|
GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
|
2016-11-11 17:43:54 +07:00
|
|
|
return 0;
|
2017-01-12 04:09:26 +07:00
|
|
|
}
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
return __i915_vma_do_pin(vma, size, alignment, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int i915_vma_pin_count(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return vma->flags & I915_VMA_PIN_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool i915_vma_is_pinned(const struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
return i915_vma_pin_count(vma);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __i915_vma_pin(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
vma->flags++;
|
|
|
|
GEM_BUG_ON(vma->flags & I915_VMA_PIN_OVERFLOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __i915_vma_unpin(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
vma->flags--;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void i915_vma_unpin(struct i915_vma *vma)
|
|
|
|
{
|
2017-07-21 21:50:34 +07:00
|
|
|
GEM_BUG_ON(!i915_vma_is_pinned(vma));
|
2016-11-11 17:43:54 +07:00
|
|
|
GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
|
|
|
|
__i915_vma_unpin(vma);
|
|
|
|
}
|
|
|
|
|
2018-06-12 19:04:46 +07:00
|
|
|
static inline bool i915_vma_is_bound(const struct i915_vma *vma,
|
|
|
|
unsigned int where)
|
|
|
|
{
|
|
|
|
return vma->flags & where;
|
|
|
|
}
|
|
|
|
|
2016-11-11 17:43:54 +07:00
|
|
|
/**
|
|
|
|
* i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture
|
|
|
|
* @vma: VMA to iomap
|
|
|
|
*
|
|
|
|
* The passed in VMA has to be pinned in the global GTT mappable region.
|
|
|
|
* An extra pinning of the VMA is acquired for the return iomapping,
|
|
|
|
* the caller must call i915_vma_unpin_iomap to relinquish the pinning
|
|
|
|
* after the iomapping is no longer required.
|
|
|
|
*
|
|
|
|
* Callers must hold the struct_mutex.
|
|
|
|
*
|
|
|
|
* Returns a valid iomapped pointer or ERR_PTR.
|
|
|
|
*/
|
|
|
|
void __iomem *i915_vma_pin_iomap(struct i915_vma *vma);
|
|
|
|
#define IO_ERR_PTR(x) ((void __iomem *)ERR_PTR(x))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap
|
|
|
|
* @vma: VMA to unpin
|
|
|
|
*
|
|
|
|
* Unpins the previously iomapped VMA from i915_vma_pin_iomap().
|
|
|
|
*
|
|
|
|
* Callers must hold the struct_mutex. This function is only valid to be
|
|
|
|
* called on a VMA previously iomapped by the caller with i915_vma_pin_iomap().
|
|
|
|
*/
|
2017-10-09 15:43:55 +07:00
|
|
|
void i915_vma_unpin_iomap(struct i915_vma *vma);
|
2016-11-11 17:43:54 +07:00
|
|
|
|
|
|
|
static inline struct page *i915_vma_first_page(struct i915_vma *vma)
|
|
|
|
{
|
|
|
|
GEM_BUG_ON(!vma->pages);
|
|
|
|
return sg_page(vma->pages->sgl);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* i915_vma_pin_fence - pin fencing state
|
|
|
|
* @vma: vma to pin fencing for
|
|
|
|
*
|
|
|
|
* This pins the fencing state (whether tiled or untiled) to make sure the
|
|
|
|
* vma (and its object) is ready to be used as a scanout target. Fencing
|
|
|
|
* status must be synchronize first by calling i915_vma_get_fence():
|
|
|
|
*
|
|
|
|
* The resulting fence pin reference must be released again with
|
|
|
|
* i915_vma_unpin_fence().
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
*
|
|
|
|
* True if the vma has a fence, false otherwise.
|
|
|
|
*/
|
2017-10-09 15:43:56 +07:00
|
|
|
int i915_vma_pin_fence(struct i915_vma *vma);
|
|
|
|
int __must_check i915_vma_put_fence(struct i915_vma *vma);
|
|
|
|
|
|
|
|
static inline void __i915_vma_unpin_fence(struct i915_vma *vma)
|
2016-11-11 17:43:54 +07:00
|
|
|
{
|
2017-10-09 15:43:56 +07:00
|
|
|
GEM_BUG_ON(vma->fence->pin_count <= 0);
|
|
|
|
vma->fence->pin_count--;
|
2016-11-11 17:43:54 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* i915_vma_unpin_fence - unpin fencing state
|
|
|
|
* @vma: vma to unpin fencing for
|
|
|
|
*
|
|
|
|
* This releases the fence pin reference acquired through
|
|
|
|
* i915_vma_pin_fence. It will handle both objects with and without an
|
|
|
|
* attached fence correctly, callers do not need to distinguish this.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
i915_vma_unpin_fence(struct i915_vma *vma)
|
|
|
|
{
|
2018-06-07 22:40:45 +07:00
|
|
|
/* lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); */
|
2017-10-09 15:43:56 +07:00
|
|
|
if (vma->fence)
|
|
|
|
__i915_vma_unpin_fence(vma);
|
2016-11-11 17:43:54 +07:00
|
|
|
}
|
|
|
|
|
2018-05-04 02:51:14 +07:00
|
|
|
void i915_vma_parked(struct drm_i915_private *i915);
|
|
|
|
|
2017-12-08 04:14:07 +07:00
|
|
|
#define for_each_until(cond) if (cond) break; else
|
|
|
|
|
|
|
|
/**
|
|
|
|
* for_each_ggtt_vma - Iterate over the GGTT VMA belonging to an object.
|
|
|
|
* @V: the #i915_vma iterator
|
|
|
|
* @OBJ: the #drm_i915_gem_object
|
|
|
|
*
|
|
|
|
* GGTT VMA are placed at the being of the object's vma_list, see
|
|
|
|
* vma_create(), so we can stop our walk as soon as we see a ppgtt VMA,
|
|
|
|
* or the list is empty ofc.
|
|
|
|
*/
|
|
|
|
#define for_each_ggtt_vma(V, OBJ) \
|
2019-01-28 17:23:54 +07:00
|
|
|
list_for_each_entry(V, &(OBJ)->vma.list, obj_link) \
|
2017-12-08 04:14:07 +07:00
|
|
|
for_each_until(!i915_vma_is_ggtt(V))
|
2016-11-11 17:43:54 +07:00
|
|
|
|
2019-02-28 17:20:34 +07:00
|
|
|
struct i915_vma *i915_vma_alloc(void);
|
|
|
|
void i915_vma_free(struct i915_vma *vma);
|
|
|
|
|
2017-12-08 04:14:07 +07:00
|
|
|
#endif
|