Commit 0cf289bd authored by Chris Wilson's avatar Chris Wilson

drm/i915: Move fence register tracking from i915->mm to ggtt

As the fence registers only apply to regions inside the GGTT is makes
more sense that we track these as part of the i915_ggtt and not the
general mm. In the next patch, we will then pull the register locking
underneath the i915_ggtt.mutex.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarMika Kuoppala <mika.kuoppala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190613073254.24048-1-chris@chris-wilson.co.uk
parent 70972f51
...@@ -310,9 +310,9 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf) ...@@ -310,9 +310,9 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
/* Mark as being mmapped into userspace for later revocation */ /* Mark as being mmapped into userspace for later revocation */
assert_rpm_wakelock_held(i915); assert_rpm_wakelock_held(i915);
if (!i915_vma_set_userfault(vma) && !obj->userfault_count++) if (!i915_vma_set_userfault(vma) && !obj->userfault_count++)
list_add(&obj->userfault_link, &i915->mm.userfault_list); list_add(&obj->userfault_link, &i915->ggtt.userfault_list);
if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND) if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
intel_wakeref_auto(&i915->mm.userfault_wakeref, intel_wakeref_auto(&i915->ggtt.userfault_wakeref,
msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)); msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
GEM_BUG_ON(!obj->userfault_count); GEM_BUG_ON(!obj->userfault_count);
......
...@@ -126,7 +126,7 @@ void i915_gem_suspend(struct drm_i915_private *i915) ...@@ -126,7 +126,7 @@ void i915_gem_suspend(struct drm_i915_private *i915)
{ {
GEM_TRACE("\n"); GEM_TRACE("\n");
intel_wakeref_auto(&i915->mm.userfault_wakeref, 0); intel_wakeref_auto(&i915->ggtt.userfault_wakeref, 0);
flush_workqueue(i915->wq); flush_workqueue(i915->wq);
mutex_lock(&i915->drm.struct_mutex); mutex_lock(&i915->drm.struct_mutex);
......
...@@ -695,19 +695,19 @@ static void revoke_mmaps(struct drm_i915_private *i915) ...@@ -695,19 +695,19 @@ static void revoke_mmaps(struct drm_i915_private *i915)
{ {
int i; int i;
for (i = 0; i < i915->num_fence_regs; i++) { for (i = 0; i < i915->ggtt.num_fences; i++) {
struct drm_vma_offset_node *node; struct drm_vma_offset_node *node;
struct i915_vma *vma; struct i915_vma *vma;
u64 vma_offset; u64 vma_offset;
vma = READ_ONCE(i915->fence_regs[i].vma); vma = READ_ONCE(i915->ggtt.fence_regs[i].vma);
if (!vma) if (!vma)
continue; continue;
if (!i915_vma_has_userfault(vma)) if (!i915_vma_has_userfault(vma))
continue; continue;
GEM_BUG_ON(vma->fence != &i915->fence_regs[i]); GEM_BUG_ON(vma->fence != &i915->ggtt.fence_regs[i]);
node = &vma->obj->base.vma_node; node = &vma->obj->base.vma_node;
vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT; vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT;
unmap_mapping_range(i915->drm.anon_inode->i_mapping, unmap_mapping_range(i915->drm.anon_inode->i_mapping,
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
*/ */
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_gem_fence_reg.h"
#include "gvt.h" #include "gvt.h"
static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
...@@ -128,7 +129,7 @@ void intel_vgpu_write_fence(struct intel_vgpu *vgpu, ...@@ -128,7 +129,7 @@ void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
{ {
struct intel_gvt *gvt = vgpu->gvt; struct intel_gvt *gvt = vgpu->gvt;
struct drm_i915_private *dev_priv = gvt->dev_priv; struct drm_i915_private *dev_priv = gvt->dev_priv;
struct drm_i915_fence_reg *reg; struct i915_fence_reg *reg;
i915_reg_t fence_reg_lo, fence_reg_hi; i915_reg_t fence_reg_lo, fence_reg_hi;
assert_rpm_wakelock_held(dev_priv); assert_rpm_wakelock_held(dev_priv);
...@@ -163,7 +164,7 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu) ...@@ -163,7 +164,7 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
{ {
struct intel_gvt *gvt = vgpu->gvt; struct intel_gvt *gvt = vgpu->gvt;
struct drm_i915_private *dev_priv = gvt->dev_priv; struct drm_i915_private *dev_priv = gvt->dev_priv;
struct drm_i915_fence_reg *reg; struct i915_fence_reg *reg;
u32 i; u32 i;
if (WARN_ON(!vgpu_fence_sz(vgpu))) if (WARN_ON(!vgpu_fence_sz(vgpu)))
...@@ -187,7 +188,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu) ...@@ -187,7 +188,7 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
{ {
struct intel_gvt *gvt = vgpu->gvt; struct intel_gvt *gvt = vgpu->gvt;
struct drm_i915_private *dev_priv = gvt->dev_priv; struct drm_i915_private *dev_priv = gvt->dev_priv;
struct drm_i915_fence_reg *reg; struct i915_fence_reg *reg;
int i; int i;
intel_runtime_pm_get(dev_priv); intel_runtime_pm_get(dev_priv);
......
...@@ -87,7 +87,7 @@ struct intel_vgpu_gm { ...@@ -87,7 +87,7 @@ struct intel_vgpu_gm {
/* Fences owned by a vGPU */ /* Fences owned by a vGPU */
struct intel_vgpu_fence { struct intel_vgpu_fence {
struct drm_i915_fence_reg *regs[INTEL_GVT_MAX_NUM_FENCES]; struct i915_fence_reg *regs[INTEL_GVT_MAX_NUM_FENCES];
u32 base; u32 base;
u32 size; u32 size;
}; };
...@@ -390,7 +390,7 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt); ...@@ -390,7 +390,7 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt);
#define gvt_hidden_gmadr_end(gvt) (gvt_hidden_gmadr_base(gvt) \ #define gvt_hidden_gmadr_end(gvt) (gvt_hidden_gmadr_base(gvt) \
+ gvt_hidden_sz(gvt) - 1) + gvt_hidden_sz(gvt) - 1)
#define gvt_fence_sz(gvt) (gvt->dev_priv->num_fence_regs) #define gvt_fence_sz(gvt) ((gvt)->dev_priv->ggtt.num_fences)
/* Aperture/GM space definitions for vGPU */ /* Aperture/GM space definitions for vGPU */
#define vgpu_aperture_offset(vgpu) ((vgpu)->gm.low_gm_node.start) #define vgpu_aperture_offset(vgpu) ((vgpu)->gm.low_gm_node.start)
......
...@@ -143,8 +143,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) ...@@ -143,8 +143,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
unsigned int frontbuffer_bits; unsigned int frontbuffer_bits;
int pin_count = 0; int pin_count = 0;
lockdep_assert_held(&obj->base.dev->struct_mutex);
seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x %s%s%s", seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x %s%s%s",
&obj->base, &obj->base,
get_active_flag(obj), get_active_flag(obj),
...@@ -160,17 +158,17 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) ...@@ -160,17 +158,17 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : ""); obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : "");
if (obj->base.name) if (obj->base.name)
seq_printf(m, " (name: %d)", obj->base.name); seq_printf(m, " (name: %d)", obj->base.name);
list_for_each_entry(vma, &obj->vma.list, obj_link) {
if (i915_vma_is_pinned(vma)) spin_lock(&obj->vma.lock);
pin_count++;
}
seq_printf(m, " (pinned x %d)", pin_count);
if (obj->pin_global)
seq_printf(m, " (global)");
list_for_each_entry(vma, &obj->vma.list, obj_link) { list_for_each_entry(vma, &obj->vma.list, obj_link) {
if (!drm_mm_node_allocated(&vma->node)) if (!drm_mm_node_allocated(&vma->node))
continue; continue;
spin_unlock(&obj->vma.lock);
if (i915_vma_is_pinned(vma))
pin_count++;
seq_printf(m, " (%sgtt offset: %08llx, size: %08llx, pages: %s", seq_printf(m, " (%sgtt offset: %08llx, size: %08llx, pages: %s",
i915_vma_is_ggtt(vma) ? "g" : "pp", i915_vma_is_ggtt(vma) ? "g" : "pp",
vma->node.start, vma->node.size, vma->node.start, vma->node.size,
...@@ -221,9 +219,16 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) ...@@ -221,9 +219,16 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
vma->fence->id, vma->fence->id,
i915_active_request_isset(&vma->last_fence) ? "*" : ""); i915_active_request_isset(&vma->last_fence) ? "*" : "");
seq_puts(m, ")"); seq_puts(m, ")");
spin_lock(&obj->vma.lock);
} }
spin_unlock(&obj->vma.lock);
seq_printf(m, " (pinned x %d)", pin_count);
if (obj->stolen) if (obj->stolen)
seq_printf(m, " (stolen: %08llx)", obj->stolen->start); seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
if (obj->pin_global)
seq_printf(m, " (global)");
engine = i915_gem_object_last_write_engine(obj); engine = i915_gem_object_last_write_engine(obj);
if (engine) if (engine)
...@@ -698,28 +703,25 @@ static int i915_interrupt_info(struct seq_file *m, void *data) ...@@ -698,28 +703,25 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
static int i915_gem_fence_regs_info(struct seq_file *m, void *data) static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
{ {
struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_i915_private *i915 = node_to_i915(m->private);
struct drm_device *dev = &dev_priv->drm; unsigned int i;
int i, ret;
ret = mutex_lock_interruptible(&dev->struct_mutex); seq_printf(m, "Total fences = %d\n", i915->ggtt.num_fences);
if (ret)
return ret;
seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); rcu_read_lock();
for (i = 0; i < dev_priv->num_fence_regs; i++) { for (i = 0; i < i915->ggtt.num_fences; i++) {
struct i915_vma *vma = dev_priv->fence_regs[i].vma; struct i915_vma *vma = i915->ggtt.fence_regs[i].vma;
seq_printf(m, "Fence %d, pin count = %d, object = ", seq_printf(m, "Fence %d, pin count = %d, object = ",
i, dev_priv->fence_regs[i].pin_count); i, i915->ggtt.fence_regs[i].pin_count);
if (!vma) if (!vma)
seq_puts(m, "unused"); seq_puts(m, "unused");
else else
describe_obj(m, vma->obj); describe_obj(m, vma->obj);
seq_putc(m, '\n'); seq_putc(m, '\n');
} }
rcu_read_unlock();
mutex_unlock(&dev->struct_mutex);
return 0; return 0;
} }
......
...@@ -350,7 +350,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data, ...@@ -350,7 +350,7 @@ static int i915_getparam_ioctl(struct drm_device *dev, void *data,
value = pdev->revision; value = pdev->revision;
break; break;
case I915_PARAM_NUM_FENCES_AVAIL: case I915_PARAM_NUM_FENCES_AVAIL:
value = dev_priv->num_fence_regs; value = dev_priv->ggtt.num_fences;
break; break;
case I915_PARAM_HAS_OVERLAY: case I915_PARAM_HAS_OVERLAY:
value = dev_priv->overlay ? 1 : 0; value = dev_priv->overlay ? 1 : 0;
...@@ -1625,7 +1625,6 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) ...@@ -1625,7 +1625,6 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
intel_uncore_sanitize(dev_priv); intel_uncore_sanitize(dev_priv);
intel_gt_init_workarounds(dev_priv); intel_gt_init_workarounds(dev_priv);
i915_gem_load_init_fences(dev_priv);
/* On the 945G/GM, the chipset reports the MSI capability on the /* On the 945G/GM, the chipset reports the MSI capability on the
* integrated graphics even though the support isn't actually there * integrated graphics even though the support isn't actually there
......
...@@ -757,14 +757,6 @@ struct i915_gem_mm { ...@@ -757,14 +757,6 @@ struct i915_gem_mm {
*/ */
struct list_head shrink_list; struct list_head shrink_list;
/** List of all objects in gtt_space, currently mmaped by userspace.
* All objects within this list must also be on bound_list.
*/
struct list_head userfault_list;
/* Manual runtime pm autosuspend delay for user GGTT mmaps */
struct intel_wakeref_auto userfault_wakeref;
/** /**
* List of objects which are pending destruction. * List of objects which are pending destruction.
*/ */
...@@ -794,9 +786,6 @@ struct i915_gem_mm { ...@@ -794,9 +786,6 @@ struct i915_gem_mm {
struct notifier_block vmap_notifier; struct notifier_block vmap_notifier;
struct shrinker shrinker; struct shrinker shrinker;
/** LRU list of objects with fence regs on them. */
struct list_head fence_list;
/** /**
* Workqueue to fault in userptr pages, flushed by the execbuf * Workqueue to fault in userptr pages, flushed by the execbuf
* when required but otherwise left to userspace to try again * when required but otherwise left to userspace to try again
...@@ -1485,9 +1474,6 @@ struct drm_i915_private { ...@@ -1485,9 +1474,6 @@ struct drm_i915_private {
/* protects panel power sequencer state */ /* protects panel power sequencer state */
struct mutex pps_mutex; struct mutex pps_mutex;
struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
unsigned int fsb_freq, mem_freq, is_ddr3; unsigned int fsb_freq, mem_freq, is_ddr3;
unsigned int skl_preferred_vco_freq; unsigned int skl_preferred_vco_freq;
unsigned int max_cdclk_freq; unsigned int max_cdclk_freq;
...@@ -2541,7 +2527,6 @@ void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv); ...@@ -2541,7 +2527,6 @@ void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv);
void i915_gem_sanitize(struct drm_i915_private *i915); void i915_gem_sanitize(struct drm_i915_private *i915);
int i915_gem_init_early(struct drm_i915_private *dev_priv); int i915_gem_init_early(struct drm_i915_private *dev_priv);
void i915_gem_cleanup_early(struct drm_i915_private *dev_priv); void i915_gem_cleanup_early(struct drm_i915_private *dev_priv);
void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
int i915_gem_freeze(struct drm_i915_private *dev_priv); int i915_gem_freeze(struct drm_i915_private *dev_priv);
int i915_gem_freeze_late(struct drm_i915_private *dev_priv); int i915_gem_freeze_late(struct drm_i915_private *dev_priv);
...@@ -2661,19 +2646,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, ...@@ -2661,19 +2646,6 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
struct dma_buf *i915_gem_prime_export(struct drm_device *dev, struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gem_obj, int flags); struct drm_gem_object *gem_obj, int flags);
/* i915_gem_fence_reg.c */
struct drm_i915_fence_reg *
i915_reserve_fence(struct drm_i915_private *dev_priv);
void i915_unreserve_fence(struct drm_i915_fence_reg *fence);
void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
void i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv);
void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
struct sg_table *pages);
void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
struct sg_table *pages);
static inline struct i915_gem_context * static inline struct i915_gem_context *
__i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id) __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
{ {
......
...@@ -884,7 +884,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, ...@@ -884,7 +884,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
return 0; return 0;
} }
void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv) void i915_gem_runtime_suspend(struct drm_i915_private *i915)
{ {
struct drm_i915_gem_object *obj, *on; struct drm_i915_gem_object *obj, *on;
int i; int i;
...@@ -897,17 +897,19 @@ void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv) ...@@ -897,17 +897,19 @@ void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
*/ */
list_for_each_entry_safe(obj, on, list_for_each_entry_safe(obj, on,
&dev_priv->mm.userfault_list, userfault_link) &i915->ggtt.userfault_list, userfault_link)
__i915_gem_object_release_mmap(obj); __i915_gem_object_release_mmap(obj);
/* The fence will be lost when the device powers down. If any were /*
* The fence will be lost when the device powers down. If any were
* in use by hardware (i.e. they are pinned), we should not be powering * in use by hardware (i.e. they are pinned), we should not be powering
* down! All other fences will be reacquired by the user upon waking. * down! All other fences will be reacquired by the user upon waking.
*/ */
for (i = 0; i < dev_priv->num_fence_regs; i++) { for (i = 0; i < i915->ggtt.num_fences; i++) {
struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; struct i915_fence_reg *reg = &i915->ggtt.fence_regs[i];
/* Ideally we want to assert that the fence register is not /*
* Ideally we want to assert that the fence register is not
* live at this point (i.e. that no piece of code will be * live at this point (i.e. that no piece of code will be
* trying to write through fence + GTT, as that both violates * trying to write through fence + GTT, as that both violates
* our tracking of activity and associated locking/barriers, * our tracking of activity and associated locking/barriers,
...@@ -1687,7 +1689,7 @@ void i915_gem_fini_hw(struct drm_i915_private *dev_priv) ...@@ -1687,7 +1689,7 @@ void i915_gem_fini_hw(struct drm_i915_private *dev_priv)
{ {
GEM_BUG_ON(dev_priv->gt.awake); GEM_BUG_ON(dev_priv->gt.awake);
intel_wakeref_auto_fini(&dev_priv->mm.userfault_wakeref); intel_wakeref_auto_fini(&dev_priv->ggtt.userfault_wakeref);
i915_gem_suspend_late(dev_priv); i915_gem_suspend_late(dev_priv);
intel_disable_gt_powersave(dev_priv); intel_disable_gt_powersave(dev_priv);
...@@ -1729,38 +1731,6 @@ void i915_gem_init_mmio(struct drm_i915_private *i915) ...@@ -1729,38 +1731,6 @@ void i915_gem_init_mmio(struct drm_i915_private *i915)
i915_gem_sanitize(i915); i915_gem_sanitize(i915);
} }
void
i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
{
int i;
if (INTEL_GEN(dev_priv) >= 7 && !IS_VALLEYVIEW(dev_priv) &&
!IS_CHERRYVIEW(dev_priv))
dev_priv->num_fence_regs = 32;
else if (INTEL_GEN(dev_priv) >= 4 ||
IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
IS_G33(dev_priv) || IS_PINEVIEW(dev_priv))
dev_priv->num_fence_regs = 16;
else
dev_priv->num_fence_regs = 8;
if (intel_vgpu_active(dev_priv))
dev_priv->num_fence_regs =
I915_READ(vgtif_reg(avail_rs.fence_num));
/* Initialize fence registers to zero */
for (i = 0; i < dev_priv->num_fence_regs; i++) {
struct drm_i915_fence_reg *fence = &dev_priv->fence_regs[i];
fence->i915 = dev_priv;
fence->id = i;
list_add_tail(&fence->link, &dev_priv->mm.fence_list);
}
i915_gem_restore_fences(dev_priv);
i915_gem_detect_bit_6_swizzle(dev_priv);
}
static void i915_gem_init__mm(struct drm_i915_private *i915) static void i915_gem_init__mm(struct drm_i915_private *i915)
{ {
spin_lock_init(&i915->mm.obj_lock); spin_lock_init(&i915->mm.obj_lock);
...@@ -1770,10 +1740,6 @@ static void i915_gem_init__mm(struct drm_i915_private *i915) ...@@ -1770,10 +1740,6 @@ static void i915_gem_init__mm(struct drm_i915_private *i915)
INIT_LIST_HEAD(&i915->mm.purge_list); INIT_LIST_HEAD(&i915->mm.purge_list);
INIT_LIST_HEAD(&i915->mm.shrink_list); INIT_LIST_HEAD(&i915->mm.shrink_list);
INIT_LIST_HEAD(&i915->mm.fence_list);
INIT_LIST_HEAD(&i915->mm.userfault_list);
intel_wakeref_auto_init(&i915->mm.userfault_wakeref, i915);
i915_gem_init__objects(i915); i915_gem_init__objects(i915);
} }
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_scatterlist.h" #include "i915_scatterlist.h"
#include "i915_vgpu.h"
/** /**
* DOC: fence register handling * DOC: fence register handling
...@@ -58,7 +59,7 @@ ...@@ -58,7 +59,7 @@
#define pipelined 0 #define pipelined 0
static void i965_write_fence_reg(struct drm_i915_fence_reg *fence, static void i965_write_fence_reg(struct i915_fence_reg *fence,
struct i915_vma *vma) struct i915_vma *vma)
{ {
i915_reg_t fence_reg_lo, fence_reg_hi; i915_reg_t fence_reg_lo, fence_reg_hi;
...@@ -115,7 +116,7 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *fence, ...@@ -115,7 +116,7 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *fence,
} }
} }
static void i915_write_fence_reg(struct drm_i915_fence_reg *fence, static void i915_write_fence_reg(struct i915_fence_reg *fence,
struct i915_vma *vma) struct i915_vma *vma)
{ {
u32 val; u32 val;
...@@ -155,7 +156,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *fence, ...@@ -155,7 +156,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *fence,
} }
} }
static void i830_write_fence_reg(struct drm_i915_fence_reg *fence, static void i830_write_fence_reg(struct i915_fence_reg *fence,
struct i915_vma *vma) struct i915_vma *vma)
{ {
u32 val; u32 val;
...@@ -187,7 +188,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *fence, ...@@ -187,7 +188,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *fence,
} }
} }
static void fence_write(struct drm_i915_fence_reg *fence, static void fence_write(struct i915_fence_reg *fence,
struct i915_vma *vma) struct i915_vma *vma)
{ {
/* /*
...@@ -211,7 +212,7 @@ static void fence_write(struct drm_i915_fence_reg *fence, ...@@ -211,7 +212,7 @@ static void fence_write(struct drm_i915_fence_reg *fence,
fence->dirty = false; fence->dirty = false;
} }
static int fence_update(struct drm_i915_fence_reg *fence, static int fence_update(struct i915_fence_reg *fence,
struct i915_vma *vma) struct i915_vma *vma)
{ {
intel_wakeref_t wakeref; intel_wakeref_t wakeref;
...@@ -256,7 +257,7 @@ static int fence_update(struct drm_i915_fence_reg *fence, ...@@ -256,7 +257,7 @@ static int fence_update(struct drm_i915_fence_reg *fence,
old->fence = NULL; old->fence = NULL;
} }
list_move(&fence->link, &fence->i915->mm.fence_list); list_move(&fence->link, &fence->i915->ggtt.fence_list);
} }
/* /*
...@@ -280,7 +281,7 @@ static int fence_update(struct drm_i915_fence_reg *fence, ...@@ -280,7 +281,7 @@ static int fence_update(struct drm_i915_fence_reg *fence,
if (vma) { if (vma) {
vma->fence = fence; vma->fence = fence;
list_move_tail(&fence->link, &fence->i915->mm.fence_list); list_move_tail(&fence->link, &fence->i915->ggtt.fence_list);
} }
intel_runtime_pm_put(fence->i915, wakeref); intel_runtime_pm_put(fence->i915, wakeref);
...@@ -300,7 +301,7 @@ static int fence_update(struct drm_i915_fence_reg *fence, ...@@ -300,7 +301,7 @@ static int fence_update(struct drm_i915_fence_reg *fence,
*/ */
int i915_vma_put_fence(struct i915_vma *vma) int i915_vma_put_fence(struct i915_vma *vma)
{ {
struct drm_i915_fence_reg *fence = vma->fence; struct i915_fence_reg *fence = vma->fence;
if (!fence) if (!fence)
return 0; return 0;
...@@ -311,11 +312,11 @@ int i915_vma_put_fence(struct i915_vma *vma) ...@@ -311,11 +312,11 @@ int i915_vma_put_fence(struct i915_vma *vma)
return fence_update(fence, NULL); return fence_update(fence, NULL);
} }
static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *i915) static struct i915_fence_reg *fence_find(struct drm_i915_private *i915)
{ {
struct drm_i915_fence_reg *fence; struct i915_fence_reg *fence;
list_for_each_entry(fence, &i915->mm.fence_list, link) { list_for_each_entry(fence, &i915->ggtt.fence_list, link) {
GEM_BUG_ON(fence->vma && fence->vma->fence != fence); GEM_BUG_ON(fence->vma && fence->vma->fence != fence);
if (fence->pin_count) if (fence->pin_count)
...@@ -349,10 +350,9 @@ static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *i915) ...@@ -349,10 +350,9 @@ static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *i915)
* *
* 0 on success, negative error code on failure. * 0 on success, negative error code on failure.
*/ */
int int i915_vma_pin_fence(struct i915_vma *vma)
i915_vma_pin_fence(struct i915_vma *vma)
{ {
struct drm_i915_fence_reg *fence; struct i915_fence_reg *fence;
struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
int err; int err;
...@@ -369,7 +369,7 @@ i915_vma_pin_fence(struct i915_vma *vma) ...@@ -369,7 +369,7 @@ i915_vma_pin_fence(struct i915_vma *vma)
fence->pin_count++; fence->pin_count++;
if (!fence->dirty) { if (!fence->dirty) {
list_move_tail(&fence->link, list_move_tail(&fence->link,
&fence->i915->mm.fence_list); &fence->i915->ggtt.fence_list);
return 0; return 0;
} }
} else if (set) { } else if (set) {
...@@ -404,10 +404,9 @@ i915_vma_pin_fence(struct i915_vma *vma) ...@@ -404,10 +404,9 @@ i915_vma_pin_fence(struct i915_vma *vma)
* This function walks the fence regs looking for a free one and remove * This function walks the fence regs looking for a free one and remove
* it from the fence_list. It is used to reserve fence for vGPU to use. * it from the fence_list. It is used to reserve fence for vGPU to use.
*/ */
struct drm_i915_fence_reg * struct i915_fence_reg *i915_reserve_fence(struct drm_i915_private *i915)
i915_reserve_fence(struct drm_i915_private *i915)
{ {
struct drm_i915_fence_reg *fence; struct i915_fence_reg *fence;
int count; int count;
int ret; int ret;
...@@ -415,7 +414,7 @@ i915_reserve_fence(struct drm_i915_private *i915) ...@@ -415,7 +414,7 @@ i915_reserve_fence(struct drm_i915_private *i915)
/* Keep at least one fence available for the display engine. */ /* Keep at least one fence available for the display engine. */
count = 0; count = 0;
list_for_each_entry(fence, &i915->mm.fence_list, link) list_for_each_entry(fence, &i915->ggtt.fence_list, link)
count += !fence->pin_count; count += !fence->pin_count;
if (count <= 1) if (count <= 1)
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
...@@ -441,11 +440,11 @@ i915_reserve_fence(struct drm_i915_private *i915) ...@@ -441,11 +440,11 @@ i915_reserve_fence(struct drm_i915_private *i915)
* *
* This function add a reserved fence register from vGPU to the fence_list. * This function add a reserved fence register from vGPU to the fence_list.
*/ */
void i915_unreserve_fence(struct drm_i915_fence_reg *fence) void i915_unreserve_fence(struct i915_fence_reg *fence)
{ {
lockdep_assert_held(&fence->i915->drm.struct_mutex); lockdep_assert_held(&fence->i915->drm.struct_mutex);
list_add(&fence->link, &fence->i915->mm.fence_list); list_add(&fence->link, &fence->i915->ggtt.fence_list);
} }
/** /**
...@@ -461,8 +460,8 @@ void i915_gem_restore_fences(struct drm_i915_private *i915) ...@@ -461,8 +460,8 @@ void i915_gem_restore_fences(struct drm_i915_private *i915)
int i; int i;
rcu_read_lock(); /* keep obj alive as we dereference */ rcu_read_lock(); /* keep obj alive as we dereference */
for (i = 0; i < i915->num_fence_regs; i++) { for (i = 0; i < i915->ggtt.num_fences; i++) {
struct drm_i915_fence_reg *reg = &i915->fence_regs[i]; struct i915_fence_reg *reg = &i915->ggtt.fence_regs[i];
struct i915_vma *vma = READ_ONCE(reg->vma); struct i915_vma *vma = READ_ONCE(reg->vma);
GEM_BUG_ON(vma && vma->fence != reg); GEM_BUG_ON(vma && vma->fence != reg);
...@@ -534,8 +533,7 @@ void i915_gem_restore_fences(struct drm_i915_private *i915) ...@@ -534,8 +533,7 @@ void i915_gem_restore_fences(struct drm_i915_private *i915)
* Detects bit 6 swizzling of address lookup between IGD access and CPU * Detects bit 6 swizzling of address lookup between IGD access and CPU
* access through main memory. * access through main memory.
*/ */
void static void detect_bit_6_swizzle(struct drm_i915_private *i915)
i915_gem_detect_bit_6_swizzle(struct drm_i915_private *i915)
{ {
struct intel_uncore *uncore = &i915->uncore; struct intel_uncore *uncore = &i915->uncore;
u32 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; u32 swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
...@@ -708,8 +706,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_i915_private *i915) ...@@ -708,8 +706,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_i915_private *i915)
* bit 17 of its physical address and therefore being interpreted differently * bit 17 of its physical address and therefore being interpreted differently
* by the GPU. * by the GPU.
*/ */
static void static void i915_gem_swizzle_page(struct page *page)
i915_gem_swizzle_page(struct page *page)
{ {
char temp[64]; char temp[64];
char *vaddr; char *vaddr;
...@@ -798,3 +795,42 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj, ...@@ -798,3 +795,42 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
i++; i++;
} }
} }
void i915_ggtt_init_fences(struct i915_ggtt *ggtt)
{
struct drm_i915_private *i915 = ggtt->vm.i915;
int num_fences;
int i;
INIT_LIST_HEAD(&ggtt->fence_list);
INIT_LIST_HEAD(&ggtt->userfault_list);
intel_wakeref_auto_init(&ggtt->userfault_wakeref, i915);
detect_bit_6_swizzle(i915);
if (INTEL_GEN(i915) >= 7 &&
!(IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)))
num_fences = 32;
else if (INTEL_GEN(i915) >= 4 ||
IS_I945G(i915) || IS_I945GM(i915) ||
IS_G33(i915) || IS_PINEVIEW(i915))
num_fences = 16;
else
num_fences = 8;
if (intel_vgpu_active(i915))
num_fences = intel_uncore_read(&i915->uncore,
vgtif_reg(avail_rs.fence_num));
/* Initialize fence registers to zero */
for (i = 0; i < num_fences; i++) {
struct i915_fence_reg *fence = &ggtt->fence_regs[i];
fence->i915 = i915;
fence->id = i;
list_add_tail(&fence->link, &ggtt->fence_list);
}
ggtt->num_fences = num_fences;
i915_gem_restore_fences(i915);
}
...@@ -26,13 +26,17 @@ ...@@ -26,13 +26,17 @@
#define __I915_FENCE_REG_H__ #define __I915_FENCE_REG_H__
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h>
struct drm_i915_gem_object;
struct drm_i915_private; struct drm_i915_private;
struct i915_ggtt;
struct i915_vma; struct i915_vma;
struct sg_table;
#define I965_FENCE_PAGE 4096UL #define I965_FENCE_PAGE 4096UL
struct drm_i915_fence_reg { struct i915_fence_reg {
struct list_head link; struct list_head link;
struct drm_i915_private *i915; struct drm_i915_private *i915;
struct i915_vma *vma; struct i915_vma *vma;
...@@ -49,4 +53,17 @@ struct drm_i915_fence_reg { ...@@ -49,4 +53,17 @@ struct drm_i915_fence_reg {
bool dirty; bool dirty;
}; };
/* i915_gem_fence_reg.c */
struct i915_fence_reg *i915_reserve_fence(struct drm_i915_private *i915);
void i915_unreserve_fence(struct i915_fence_reg *fence);
void i915_gem_restore_fences(struct drm_i915_private *i915);
void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
struct sg_table *pages);
void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
struct sg_table *pages);
void i915_ggtt_init_fences(struct i915_ggtt *ggtt);
#endif #endif
...@@ -3567,6 +3567,8 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv) ...@@ -3567,6 +3567,8 @@ int i915_ggtt_init_hw(struct drm_i915_private *dev_priv)
ggtt->mtrr = arch_phys_wc_add(ggtt->gmadr.start, ggtt->mappable_end); ggtt->mtrr = arch_phys_wc_add(ggtt->gmadr.start, ggtt->mappable_end);
i915_ggtt_init_fences(ggtt);
/* /*
* Initialise stolen early so that we may reserve preallocated * Initialise stolen early so that we may reserve preallocated
* objects for the BIOS to KMS transition. * objects for the BIOS to KMS transition.
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/pagevec.h> #include <linux/pagevec.h>
#include "gt/intel_reset.h" #include "gt/intel_reset.h"
#include "i915_gem_fence_reg.h"
#include "i915_request.h" #include "i915_request.h"
#include "i915_scatterlist.h" #include "i915_scatterlist.h"
#include "i915_selftest.h" #include "i915_selftest.h"
...@@ -61,7 +62,6 @@ ...@@ -61,7 +62,6 @@
#define I915_MAX_NUM_FENCE_BITS 6 #define I915_MAX_NUM_FENCE_BITS 6
struct drm_i915_file_private; struct drm_i915_file_private;
struct drm_i915_fence_reg;
struct drm_i915_gem_object; struct drm_i915_gem_object;
struct i915_vma; struct i915_vma;
...@@ -408,6 +408,18 @@ struct i915_ggtt { ...@@ -408,6 +408,18 @@ struct i915_ggtt {
u32 pin_bias; u32 pin_bias;
unsigned int num_fences;
struct i915_fence_reg fence_regs[I915_MAX_NUM_FENCES];
struct list_head fence_list;
/** List of all objects in gtt_space, currently mmaped by userspace.
* All objects within this list must also be on bound_list.
*/
struct list_head userfault_list;
/* Manual runtime pm autosuspend delay for user GGTT mmaps */
struct intel_wakeref_auto userfault_wakeref;
struct drm_mm_node error_capture; struct drm_mm_node error_capture;
struct drm_mm_node uc_fw; struct drm_mm_node uc_fw;
}; };
......
...@@ -1127,17 +1127,17 @@ static void gem_record_fences(struct i915_gpu_state *error) ...@@ -1127,17 +1127,17 @@ static void gem_record_fences(struct i915_gpu_state *error)
int i; int i;
if (INTEL_GEN(dev_priv) >= 6) { if (INTEL_GEN(dev_priv) >= 6) {
for (i = 0; i < dev_priv->num_fence_regs; i++) for (i = 0; i < dev_priv->ggtt.num_fences; i++)
error->fence[i] = error->fence[i] =
intel_uncore_read64(uncore, intel_uncore_read64(uncore,
FENCE_REG_GEN6_LO(i)); FENCE_REG_GEN6_LO(i));
} else if (INTEL_GEN(dev_priv) >= 4) { } else if (INTEL_GEN(dev_priv) >= 4) {
for (i = 0; i < dev_priv->num_fence_regs; i++) for (i = 0; i < dev_priv->ggtt.num_fences; i++)
error->fence[i] = error->fence[i] =
intel_uncore_read64(uncore, intel_uncore_read64(uncore,
FENCE_REG_965_LO(i)); FENCE_REG_965_LO(i));
} else { } else {
for (i = 0; i < dev_priv->num_fence_regs; i++) for (i = 0; i < dev_priv->ggtt.num_fences; i++)
error->fence[i] = error->fence[i] =
intel_uncore_read(uncore, FENCE_REG(i)); intel_uncore_read(uncore, FENCE_REG(i));
} }
......
...@@ -54,7 +54,7 @@ struct i915_vma { ...@@ -54,7 +54,7 @@ struct i915_vma {
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct i915_address_space *vm; struct i915_address_space *vm;
const struct i915_vma_ops *ops; const struct i915_vma_ops *ops;
struct drm_i915_fence_reg *fence; struct i915_fence_reg *fence;
struct reservation_object *resv; /** Alias of obj->resv */ struct reservation_object *resv; /** Alias of obj->resv */
struct sg_table *pages; struct sg_table *pages;
void __iomem *iomap; void __iomem *iomap;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment