You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'drm-intel-next-2017-03-06' of git://anongit.freedesktop.org/git/drm-intel into drm-next
4 weeks worth of stuff since I was traveling&lazy:
- lspcon improvements (Imre)
- proper atomic state for cdclk handling (Ville)
- gpu reset improvements (Chris)
- lots and lots of polish around fences, requests, waiting and
everything related all over (both gem and modeset code), from Chris
- atomic by default on gen5+ minus byt/bsw (Maarten did the patch to
flip the default, really this is a massive joint team effort)
- moar power domains, now 64bit (Ander)
- big pile of in-kernel unit tests for various gem subsystems (Chris),
including simple mock objects for i915 device and and the ggtt
manager.
- i915_gpu_info in debugfs, for taking a snapshot of the current gpu
state. Same thing as i915_error_state, but useful if the kernel didn't
notice something is stick. From Chris.
- bxt dsi fixes (Umar Shankar)
- bxt w/a updates (Jani)
- no more struct_mutex for gem object unreference (Chris)
- some execlist refactoring (Tvrtko)
- color manager support for glk (Ander)
- improve the power-well sync code to better take over from the
firmware (Imre)
- gem tracepoint polish (Tvrtko)
- lots of glk fixes all around (Ander)
- ctx switch improvements (Chris)
- glk dsi support&fixes (Deepak M)
- dsi fixes for vlv and clanups, lots of them (Hans de Goede)
- switch to i915.ko types in lots of our internal modeset code (Ander)
- byt/bsw atomic wm update code, yay (Ville)
* tag 'drm-intel-next-2017-03-06' of git://anongit.freedesktop.org/git/drm-intel: (432 commits)
drm/i915: Update DRIVER_DATE to 20170306
drm/i915: Don't use enums for hardware engine id
drm/i915: Split breadcrumbs spinlock into two
drm/i915: Refactor wakeup of the next breadcrumb waiter
drm/i915: Take reference for signaling the request from hardirq
drm/i915: Add FIFO underrun tracepoints
drm/i915: Add cxsr toggle tracepoint
drm/i915: Add VLV/CHV watermark/FIFO programming tracepoints
drm/i915: Add plane update/disable tracepoints
drm/i915: Kill level 0 wm hack for VLV/CHV
drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
drm/i915: Sanitize VLV/CHV watermarks properly
drm/i915: Only use update_wm_{pre,post} for pre-ilk platforms
drm/i915: Nuke crtc->wm.cxsr_allowed
drm/i915: Compute proper intermediate wms for vlv/cvh
drm/i915: Skip useless watermark/FIFO related work on VLV/CHV when not needed
drm/i915: Compute vlv/chv wms the atomic way
drm/i915: Compute VLV/CHV FIFO sizes based on the PM2 watermarks
drm/i915: Plop vlv/chv fifo sizes into crtc state
drm/i915: Plop vlv wm state into crtc_state
...
This commit is contained in:
@@ -222,6 +222,15 @@ Video BIOS Table (VBT)
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_vbt_defs.h
|
||||
:internal:
|
||||
|
||||
Display clocks
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_cdclk.c
|
||||
:doc: CDCLK / RAWCLK
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_cdclk.c
|
||||
:internal:
|
||||
|
||||
Display PLLs
|
||||
------------
|
||||
|
||||
|
||||
@@ -526,6 +526,7 @@ static const struct pci_device_id intel_early_ids[] __initconst = {
|
||||
INTEL_SKL_IDS(&gen9_early_ops),
|
||||
INTEL_BXT_IDS(&gen9_early_ops),
|
||||
INTEL_KBL_IDS(&gen9_early_ops),
|
||||
INTEL_GLK_IDS(&gen9_early_ops),
|
||||
};
|
||||
|
||||
static void __init
|
||||
|
||||
@@ -332,14 +332,6 @@ static void i810_write_entry(dma_addr_t addr, unsigned int entry,
|
||||
writel_relaxed(addr | pte_flags, intel_private.gtt + entry);
|
||||
}
|
||||
|
||||
static const struct aper_size_info_fixed intel_fake_agp_sizes[] = {
|
||||
{32, 8192, 3},
|
||||
{64, 16384, 4},
|
||||
{128, 32768, 5},
|
||||
{256, 65536, 6},
|
||||
{512, 131072, 7},
|
||||
};
|
||||
|
||||
static unsigned int intel_gtt_stolen_size(void)
|
||||
{
|
||||
u16 gmch_ctrl;
|
||||
@@ -670,6 +662,14 @@ static int intel_gtt_init(void)
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_AGP_INTEL)
|
||||
static const struct aper_size_info_fixed intel_fake_agp_sizes[] = {
|
||||
{32, 8192, 3},
|
||||
{64, 16384, 4},
|
||||
{128, 32768, 5},
|
||||
{256, 65536, 6},
|
||||
{512, 131072, 7},
|
||||
};
|
||||
|
||||
static int intel_fake_agp_fetch_size(void)
|
||||
{
|
||||
int num_sizes = ARRAY_SIZE(intel_fake_agp_sizes);
|
||||
|
||||
@@ -19,6 +19,7 @@ config DRM_I915
|
||||
select INPUT if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
select ACPI_BUTTON if ACPI
|
||||
select SYNC_FILE
|
||||
help
|
||||
Choose this option if you have a system that has "Intel Graphics
|
||||
Media Accelerator" or "HD Graphics" integrated graphics,
|
||||
|
||||
@@ -24,7 +24,9 @@ config DRM_I915_DEBUG
|
||||
select X86_MSR # used by igt/pm_rpm
|
||||
select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
|
||||
select DRM_DEBUG_MM if DRM=y
|
||||
select DRM_DEBUG_MM_SELFTEST
|
||||
select DRM_I915_SW_FENCE_DEBUG_OBJECTS
|
||||
select DRM_I915_SELFTEST
|
||||
default n
|
||||
help
|
||||
Choose this option to turn on extra driver debugging that may affect
|
||||
@@ -58,3 +60,30 @@ config DRM_I915_SW_FENCE_DEBUG_OBJECTS
|
||||
Recommended for driver developers only.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_I915_SELFTEST
|
||||
bool "Enable selftests upon driver load"
|
||||
depends on DRM_I915
|
||||
default n
|
||||
select FAULT_INJECTION
|
||||
select PRIME_NUMBERS
|
||||
help
|
||||
Choose this option to allow the driver to perform selftests upon
|
||||
loading; also requires the i915.selftest=1 module parameter. To
|
||||
exit the module after running the selftests (i.e. to prevent normal
|
||||
module initialisation afterwards) use i915.selftest=-1.
|
||||
|
||||
Recommended for driver developers only.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_I915_LOW_LEVEL_TRACEPOINTS
|
||||
bool "Enable low level request tracing events"
|
||||
depends on DRM_I915
|
||||
default n
|
||||
help
|
||||
Choose this option to turn on low level request tracing events.
|
||||
This provides the ability to precisely monitor engine utilisation
|
||||
and also analyze the request dependency resolving timeline.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
@@ -29,6 +29,7 @@ i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o
|
||||
# GEM code
|
||||
i915-y += i915_cmd_parser.o \
|
||||
i915_gem_batch_pool.o \
|
||||
i915_gem_clflush.o \
|
||||
i915_gem_context.o \
|
||||
i915_gem_dmabuf.o \
|
||||
i915_gem_evict.o \
|
||||
@@ -72,6 +73,7 @@ i915-y += intel_audio.o \
|
||||
intel_atomic.o \
|
||||
intel_atomic_plane.o \
|
||||
intel_bios.o \
|
||||
intel_cdclk.o \
|
||||
intel_color.o \
|
||||
intel_display.o \
|
||||
intel_dpio_phy.o \
|
||||
@@ -116,6 +118,9 @@ i915-y += dvo_ch7017.o \
|
||||
|
||||
# Post-mortem debug and GPU hang state capture
|
||||
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
|
||||
i915-$(CONFIG_DRM_I915_SELFTEST) += \
|
||||
selftests/i915_random.o \
|
||||
selftests/i915_selftest.o
|
||||
|
||||
# virtual gpu code
|
||||
i915-y += i915_vgpu.o
|
||||
|
||||
@@ -1530,7 +1530,7 @@ static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm,
|
||||
len += copy_len;
|
||||
gma += copy_len;
|
||||
}
|
||||
return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -1644,7 +1644,7 @@ static int perform_bb_shadow(struct parser_exec_state *s)
|
||||
ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
|
||||
gma, gma + bb_size,
|
||||
dst);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
gvt_err("fail to copy guest ring buffer\n");
|
||||
goto unmap_src;
|
||||
}
|
||||
@@ -2608,11 +2608,8 @@ out:
|
||||
static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
|
||||
{
|
||||
struct intel_vgpu *vgpu = workload->vgpu;
|
||||
int ring_id = workload->ring_id;
|
||||
struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx;
|
||||
struct intel_ring *ring = shadow_ctx->engine[ring_id].ring;
|
||||
unsigned long gma_head, gma_tail, gma_top, guest_rb_size;
|
||||
unsigned int copy_len = 0;
|
||||
u32 *cs;
|
||||
int ret;
|
||||
|
||||
guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl);
|
||||
@@ -2626,36 +2623,33 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
|
||||
gma_top = workload->rb_start + guest_rb_size;
|
||||
|
||||
/* allocate shadow ring buffer */
|
||||
ret = intel_ring_begin(workload->req, workload->rb_len / 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
cs = intel_ring_begin(workload->req, workload->rb_len / sizeof(u32));
|
||||
if (IS_ERR(cs))
|
||||
return PTR_ERR(cs);
|
||||
|
||||
/* get shadow ring buffer va */
|
||||
workload->shadow_ring_buffer_va = ring->vaddr + ring->tail;
|
||||
workload->shadow_ring_buffer_va = cs;
|
||||
|
||||
/* head > tail --> copy head <-> top */
|
||||
if (gma_head > gma_tail) {
|
||||
ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm,
|
||||
gma_head, gma_top,
|
||||
workload->shadow_ring_buffer_va);
|
||||
if (ret) {
|
||||
gma_head, gma_top, cs);
|
||||
if (ret < 0) {
|
||||
gvt_err("fail to copy guest ring buffer\n");
|
||||
return ret;
|
||||
}
|
||||
copy_len = gma_top - gma_head;
|
||||
cs += ret / sizeof(u32);
|
||||
gma_head = workload->rb_start;
|
||||
}
|
||||
|
||||
/* copy head or start <-> tail */
|
||||
ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm,
|
||||
gma_head, gma_tail,
|
||||
workload->shadow_ring_buffer_va + copy_len);
|
||||
if (ret) {
|
||||
ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, gma_head, gma_tail, cs);
|
||||
if (ret < 0) {
|
||||
gvt_err("fail to copy guest ring buffer\n");
|
||||
return ret;
|
||||
}
|
||||
ring->tail += workload->rb_len;
|
||||
intel_ring_advance(ring);
|
||||
cs += ret / sizeof(u32);
|
||||
intel_ring_advance(workload->req, cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2709,7 +2703,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)
|
||||
wa_ctx->workload->vgpu->gtt.ggtt_mm,
|
||||
guest_gma, guest_gma + ctx_size,
|
||||
map);
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
gvt_err("fail to copy guest indirect ctx\n");
|
||||
goto unmap_src;
|
||||
}
|
||||
|
||||
+252
-122
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
@@ -248,6 +249,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_IRQ_ACTIVE:
|
||||
case I915_PARAM_ALLOW_BATCHBUFFER:
|
||||
case I915_PARAM_LAST_DISPATCH:
|
||||
case I915_PARAM_HAS_EXEC_CONSTANTS:
|
||||
/* Reject all old ums/dri params. */
|
||||
return -ENODEV;
|
||||
case I915_PARAM_CHIPSET_ID:
|
||||
@@ -274,9 +276,6 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_BSD2:
|
||||
value = !!dev_priv->engine[VCS2];
|
||||
break;
|
||||
case I915_PARAM_HAS_EXEC_CONSTANTS:
|
||||
value = INTEL_GEN(dev_priv) >= 4;
|
||||
break;
|
||||
case I915_PARAM_HAS_LLC:
|
||||
value = HAS_LLC(dev_priv);
|
||||
break;
|
||||
@@ -318,10 +317,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
value = INTEL_INFO(dev_priv)->sseu.min_eu_in_pool;
|
||||
break;
|
||||
case I915_PARAM_HUC_STATUS:
|
||||
/* The register is already force-woken. We dont need
|
||||
* any rpm here
|
||||
*/
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
value = I915_READ(HUC_STATUS2) & HUC_FW_VERIFIED;
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
break;
|
||||
case I915_PARAM_MMAP_GTT_VERSION:
|
||||
/* Though we've started our numbering from 1, and so class all
|
||||
@@ -350,6 +348,8 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_EXEC_HANDLE_LUT:
|
||||
case I915_PARAM_HAS_COHERENT_PHYS_GTT:
|
||||
case I915_PARAM_HAS_EXEC_SOFTPIN:
|
||||
case I915_PARAM_HAS_EXEC_ASYNC:
|
||||
case I915_PARAM_HAS_EXEC_FENCE:
|
||||
/* For the time being all of these are always true;
|
||||
* if some supported hardware does not have one of these
|
||||
* features this value needs to be provided from
|
||||
@@ -756,6 +756,15 @@ out_err:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void i915_engines_cleanup(struct drm_i915_private *i915)
|
||||
{
|
||||
struct intel_engine_cs *engine;
|
||||
enum intel_engine_id id;
|
||||
|
||||
for_each_engine(engine, i915, id)
|
||||
kfree(engine);
|
||||
}
|
||||
|
||||
static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
destroy_workqueue(dev_priv->hotplug.dp_wq);
|
||||
@@ -769,10 +778,17 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_HSW_EARLY_SDV(dev_priv) ||
|
||||
IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
|
||||
bool pre = false;
|
||||
|
||||
pre |= IS_HSW_EARLY_SDV(dev_priv);
|
||||
pre |= IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0);
|
||||
pre |= IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST);
|
||||
|
||||
if (pre) {
|
||||
DRM_ERROR("This is a pre-production stepping. "
|
||||
"It may not be fully functional.\n");
|
||||
add_taint(TAINT_MACHINE_CHECK, LOCKDEP_STILL_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -808,6 +824,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
|
||||
spin_lock_init(&dev_priv->gpu_error.lock);
|
||||
mutex_init(&dev_priv->backlight_lock);
|
||||
spin_lock_init(&dev_priv->uncore.lock);
|
||||
|
||||
spin_lock_init(&dev_priv->mm.object_stat_lock);
|
||||
spin_lock_init(&dev_priv->mmio_flip_lock);
|
||||
spin_lock_init(&dev_priv->wm.dsparb_lock);
|
||||
@@ -818,12 +835,15 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
|
||||
mutex_init(&dev_priv->pps_mutex);
|
||||
|
||||
intel_uc_init_early(dev_priv);
|
||||
|
||||
i915_memcpy_init_early(dev_priv);
|
||||
|
||||
ret = intel_engines_init_early(dev_priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i915_workqueues_init(dev_priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err_engines;
|
||||
|
||||
/* This must be called before any calls to HAS_PCH_* */
|
||||
intel_detect_pch(dev_priv);
|
||||
@@ -852,6 +872,8 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv,
|
||||
|
||||
err_workqueues:
|
||||
i915_workqueues_cleanup(dev_priv);
|
||||
err_engines:
|
||||
i915_engines_cleanup(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -864,6 +886,7 @@ static void i915_driver_cleanup_early(struct drm_i915_private *dev_priv)
|
||||
i915_perf_fini(dev_priv);
|
||||
i915_gem_load_cleanup(dev_priv);
|
||||
i915_workqueues_cleanup(dev_priv);
|
||||
i915_engines_cleanup(dev_priv);
|
||||
}
|
||||
|
||||
static int i915_mmio_setup(struct drm_i915_private *dev_priv)
|
||||
@@ -930,6 +953,7 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv)
|
||||
goto put_bridge;
|
||||
|
||||
intel_uncore_init(dev_priv);
|
||||
i915_gem_init_mmio(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -967,7 +991,7 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv)
|
||||
DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt);
|
||||
|
||||
i915.semaphores = intel_sanitize_semaphores(dev_priv, i915.semaphores);
|
||||
DRM_DEBUG_DRIVER("use GPU sempahores? %s\n", yesno(i915.semaphores));
|
||||
DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", yesno(i915.semaphores));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1185,11 +1209,15 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
const struct intel_device_info *match_info =
|
||||
(struct intel_device_info *)ent->driver_data;
|
||||
struct drm_i915_private *dev_priv;
|
||||
int ret;
|
||||
|
||||
if (i915.nuclear_pageflip)
|
||||
driver.driver_features |= DRIVER_ATOMIC;
|
||||
/* Enable nuclear pageflip on ILK+, except vlv/chv */
|
||||
if (!i915.nuclear_pageflip &&
|
||||
(match_info->gen < 5 || match_info->has_gmch_display))
|
||||
driver.driver_features &= ~DRIVER_ATOMIC;
|
||||
|
||||
ret = -ENOMEM;
|
||||
dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
|
||||
@@ -1197,8 +1225,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
ret = drm_dev_init(&dev_priv->drm, &driver, &pdev->dev);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(&pdev->dev, "allocation failed\n");
|
||||
kfree(dev_priv);
|
||||
return ret;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
dev_priv->drm.pdev = pdev;
|
||||
@@ -1206,7 +1233,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
goto out_free_priv;
|
||||
goto out_fini;
|
||||
|
||||
pci_set_drvdata(pdev, &dev_priv->drm);
|
||||
|
||||
@@ -1270,9 +1297,11 @@ out_runtime_pm_put:
|
||||
i915_driver_cleanup_early(dev_priv);
|
||||
out_pci_disable:
|
||||
pci_disable_device(pdev);
|
||||
out_free_priv:
|
||||
out_fini:
|
||||
i915_load_error(dev_priv, "Device initialization failed (%d)\n", ret);
|
||||
drm_dev_unref(&dev_priv->drm);
|
||||
drm_dev_fini(&dev_priv->drm);
|
||||
out_free:
|
||||
kfree(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1280,6 +1309,8 @@ void i915_driver_unload(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct pci_dev *pdev = dev_priv->drm.pdev;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret;
|
||||
|
||||
intel_fbdev_fini(dev);
|
||||
|
||||
@@ -1288,6 +1319,24 @@ void i915_driver_unload(struct drm_device *dev)
|
||||
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
while (1) {
|
||||
ret = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||
if (!ret)
|
||||
ret = drm_atomic_helper_disable_all(dev, &ctx);
|
||||
|
||||
if (ret != -EDEADLK)
|
||||
break;
|
||||
|
||||
drm_modeset_backoff(&ctx);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
intel_gvt_cleanup(dev_priv);
|
||||
|
||||
i915_driver_unregister(dev_priv);
|
||||
@@ -1317,7 +1366,7 @@ void i915_driver_unload(struct drm_device *dev)
|
||||
|
||||
/* Free error state after interrupts are fully disabled. */
|
||||
cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
|
||||
i915_destroy_error_state(dev_priv);
|
||||
i915_reset_error_state(dev_priv);
|
||||
|
||||
/* Flush any outstanding unpin_work. */
|
||||
drain_workqueue(dev_priv->wq);
|
||||
@@ -1333,8 +1382,16 @@ void i915_driver_unload(struct drm_device *dev)
|
||||
i915_driver_cleanup_mmio(dev_priv);
|
||||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
||||
}
|
||||
|
||||
static void i915_driver_release(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
|
||||
i915_driver_cleanup_early(dev_priv);
|
||||
drm_dev_fini(&dev_priv->drm);
|
||||
|
||||
kfree(dev_priv);
|
||||
}
|
||||
|
||||
static int i915_driver_open(struct drm_device *dev, struct drm_file *file)
|
||||
@@ -1716,6 +1773,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
||||
!(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload))
|
||||
intel_power_domains_init_hw(dev_priv, true);
|
||||
|
||||
i915_gem_sanitize(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
out:
|
||||
@@ -1787,7 +1846,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
i915_gem_reset_finish(dev_priv);
|
||||
i915_gem_reset(dev_priv);
|
||||
intel_overlay_reset(dev_priv);
|
||||
|
||||
/* Ok, now get things going again... */
|
||||
@@ -1813,6 +1872,7 @@ void i915_reset(struct drm_i915_private *dev_priv)
|
||||
i915_queue_hangcheck(dev_priv);
|
||||
|
||||
wakeup:
|
||||
i915_gem_reset_finish(dev_priv);
|
||||
enable_irq(dev_priv->drm.irq);
|
||||
wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS);
|
||||
return;
|
||||
@@ -2532,7 +2592,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_INIT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2_WR, i915_gem_execbuffer2, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_reject_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
@@ -2574,7 +2634,8 @@ static struct drm_driver driver = {
|
||||
*/
|
||||
.driver_features =
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | DRIVER_PRIME |
|
||||
DRIVER_RENDER | DRIVER_MODESET,
|
||||
DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.release = i915_driver_release,
|
||||
.open = i915_driver_open,
|
||||
.lastclose = i915_driver_lastclose,
|
||||
.preclose = i915_driver_preclose,
|
||||
@@ -2603,3 +2664,7 @@ static struct drm_driver driver = {
|
||||
.minor = DRIVER_MINOR,
|
||||
.patchlevel = DRIVER_PATCHLEVEL,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
#include "selftests/mock_drm.c"
|
||||
#endif
|
||||
|
||||
+173
-58
@@ -79,8 +79,8 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20170123"
|
||||
#define DRIVER_TIMESTAMP 1485156432
|
||||
#define DRIVER_DATE "20170306"
|
||||
#define DRIVER_TIMESTAMP 1488785683
|
||||
|
||||
#undef WARN_ON
|
||||
/* Many gcc seem to no see through this and fall over :( */
|
||||
@@ -293,6 +293,7 @@ enum plane_id {
|
||||
PLANE_PRIMARY,
|
||||
PLANE_SPRITE0,
|
||||
PLANE_SPRITE1,
|
||||
PLANE_SPRITE2,
|
||||
PLANE_CURSOR,
|
||||
I915_MAX_PLANES,
|
||||
};
|
||||
@@ -343,6 +344,11 @@ enum intel_display_power_domain {
|
||||
POWER_DOMAIN_PORT_DDI_C_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_D_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_E_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_A_IO,
|
||||
POWER_DOMAIN_PORT_DDI_B_IO,
|
||||
POWER_DOMAIN_PORT_DDI_C_IO,
|
||||
POWER_DOMAIN_PORT_DDI_D_IO,
|
||||
POWER_DOMAIN_PORT_DDI_E_IO,
|
||||
POWER_DOMAIN_PORT_DSI,
|
||||
POWER_DOMAIN_PORT_CRT,
|
||||
POWER_DOMAIN_PORT_OTHER,
|
||||
@@ -384,6 +390,8 @@ enum hpd_pin {
|
||||
#define for_each_hpd_pin(__pin) \
|
||||
for ((__pin) = (HPD_NONE + 1); (__pin) < HPD_NUM_PINS; (__pin)++)
|
||||
|
||||
#define HPD_STORM_DEFAULT_THRESHOLD 5
|
||||
|
||||
struct i915_hotplug {
|
||||
struct work_struct hotplug_work;
|
||||
|
||||
@@ -407,6 +415,8 @@ struct i915_hotplug {
|
||||
struct work_struct poll_init_work;
|
||||
bool poll_enabled;
|
||||
|
||||
unsigned int hpd_storm_threshold;
|
||||
|
||||
/*
|
||||
* if we get a HPD irq from DP and a HPD irq from non-DP
|
||||
* the non-DP HPD could block the workqueue on a mode config
|
||||
@@ -494,7 +504,35 @@ struct i915_hotplug {
|
||||
|
||||
#define for_each_power_domain(domain, mask) \
|
||||
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
|
||||
for_each_if ((1 << (domain)) & (mask))
|
||||
for_each_if (BIT_ULL(domain) & (mask))
|
||||
|
||||
#define for_each_power_well(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells < \
|
||||
(__dev_priv)->power_domains.power_well_count; \
|
||||
(__power_well)++)
|
||||
|
||||
#define for_each_power_well_rev(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells + \
|
||||
(__dev_priv)->power_domains.power_well_count - 1; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells >= 0; \
|
||||
(__power_well)--)
|
||||
|
||||
#define for_each_power_domain_well(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well(__dev_priv, __power_well) \
|
||||
for_each_if ((__power_well)->domains & (__domain_mask))
|
||||
|
||||
#define for_each_power_domain_well_rev(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well_rev(__dev_priv, __power_well) \
|
||||
for_each_if ((__power_well)->domains & (__domain_mask))
|
||||
|
||||
#define for_each_intel_plane_in_state(__state, plane, plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
|
||||
((plane) = to_intel_plane((__state)->base.planes[__i].ptr), \
|
||||
(plane_state) = to_intel_plane_state((__state)->base.planes[__i].state), 1); \
|
||||
(__i)++) \
|
||||
for_each_if (plane_state)
|
||||
|
||||
struct drm_i915_private;
|
||||
struct i915_mm_struct;
|
||||
@@ -600,9 +638,13 @@ struct intel_initial_plane_config;
|
||||
struct intel_crtc;
|
||||
struct intel_limit;
|
||||
struct dpll;
|
||||
struct intel_cdclk_state;
|
||||
|
||||
struct drm_i915_display_funcs {
|
||||
int (*get_display_clock_speed)(struct drm_i915_private *dev_priv);
|
||||
void (*get_cdclk)(struct drm_i915_private *dev_priv,
|
||||
struct intel_cdclk_state *cdclk_state);
|
||||
void (*set_cdclk)(struct drm_i915_private *dev_priv,
|
||||
const struct intel_cdclk_state *cdclk_state);
|
||||
int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
|
||||
int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
|
||||
int (*compute_intermediate_wm)(struct drm_device *dev,
|
||||
@@ -617,7 +659,6 @@ struct drm_i915_display_funcs {
|
||||
int (*compute_global_watermarks)(struct drm_atomic_state *state);
|
||||
void (*update_wm)(struct intel_crtc *crtc);
|
||||
int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
|
||||
void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
|
||||
/* Returns the active state of the crtc, and if the crtc is active,
|
||||
* fills out the pipe-config with the hw state. */
|
||||
bool (*get_pipe_config)(struct intel_crtc *,
|
||||
@@ -636,7 +677,8 @@ struct drm_i915_display_funcs {
|
||||
struct intel_encoder *encoder,
|
||||
const struct drm_display_mode *adjusted_mode);
|
||||
void (*audio_codec_disable)(struct intel_encoder *encoder);
|
||||
void (*fdi_link_train)(struct drm_crtc *crtc);
|
||||
void (*fdi_link_train)(struct intel_crtc *crtc,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void (*init_clock_gating)(struct drm_i915_private *dev_priv);
|
||||
int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
@@ -856,6 +898,7 @@ enum intel_platform {
|
||||
INTEL_BROXTON,
|
||||
INTEL_KABYLAKE,
|
||||
INTEL_GEMINILAKE,
|
||||
INTEL_MAX_PLATFORMS
|
||||
};
|
||||
|
||||
struct intel_device_info {
|
||||
@@ -890,7 +933,7 @@ struct intel_device_info {
|
||||
|
||||
struct intel_display_error_state;
|
||||
|
||||
struct drm_i915_error_state {
|
||||
struct i915_gpu_state {
|
||||
struct kref ref;
|
||||
struct timeval time;
|
||||
struct timeval boottime;
|
||||
@@ -900,16 +943,20 @@ struct drm_i915_error_state {
|
||||
|
||||
char error_msg[128];
|
||||
bool simulated;
|
||||
bool awake;
|
||||
bool wakelock;
|
||||
bool suspended;
|
||||
int iommu;
|
||||
u32 reset_count;
|
||||
u32 suspend_count;
|
||||
struct intel_device_info device_info;
|
||||
struct i915_params params;
|
||||
|
||||
/* Generic register state */
|
||||
u32 eir;
|
||||
u32 pgtbl_er;
|
||||
u32 ier;
|
||||
u32 gtier[4];
|
||||
u32 gtier[4], ngtier;
|
||||
u32 ccid;
|
||||
u32 derrmr;
|
||||
u32 forcewake;
|
||||
@@ -923,6 +970,7 @@ struct drm_i915_error_state {
|
||||
u32 gab_ctl;
|
||||
u32 gfx_mode;
|
||||
|
||||
u32 nfence;
|
||||
u64 fence[I915_MAX_NUM_FENCES];
|
||||
struct intel_overlay_error_state *overlay;
|
||||
struct intel_display_error_state *display;
|
||||
@@ -970,6 +1018,16 @@ struct drm_i915_error_state {
|
||||
u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
|
||||
struct intel_instdone instdone;
|
||||
|
||||
struct drm_i915_error_context {
|
||||
char comm[TASK_COMM_LEN];
|
||||
pid_t pid;
|
||||
u32 handle;
|
||||
u32 hw_id;
|
||||
int ban_score;
|
||||
int active;
|
||||
int guilty;
|
||||
} context;
|
||||
|
||||
struct drm_i915_error_object {
|
||||
u64 gtt_offset;
|
||||
u64 gtt_size;
|
||||
@@ -1003,10 +1061,6 @@ struct drm_i915_error_state {
|
||||
u32 pp_dir_base;
|
||||
};
|
||||
} vm_info;
|
||||
|
||||
pid_t pid;
|
||||
char comm[TASK_COMM_LEN];
|
||||
int context_bans;
|
||||
} engine[I915_NUM_ENGINES];
|
||||
|
||||
struct drm_i915_error_buffer {
|
||||
@@ -1395,7 +1449,7 @@ struct i915_power_well {
|
||||
int count;
|
||||
/* cached hw enabled state */
|
||||
bool hw_enabled;
|
||||
unsigned long domains;
|
||||
u64 domains;
|
||||
/* unique identifier for this power well */
|
||||
unsigned long id;
|
||||
/*
|
||||
@@ -1456,7 +1510,7 @@ struct i915_gem_mm {
|
||||
struct work_struct free_work;
|
||||
|
||||
/** Usable portion of the GTT for GEM */
|
||||
phys_addr_t stolen_base; /* limited to low memory (32-bit) */
|
||||
dma_addr_t stolen_base; /* limited to low memory (32-bit) */
|
||||
|
||||
/** PPGTT used for aliasing the PPGTT with the GTT */
|
||||
struct i915_hw_ppgtt *aliasing_ppgtt;
|
||||
@@ -1498,11 +1552,6 @@ struct drm_i915_error_state_buf {
|
||||
loff_t pos;
|
||||
};
|
||||
|
||||
struct i915_error_state_file_priv {
|
||||
struct drm_i915_private *i915;
|
||||
struct drm_i915_error_state *error;
|
||||
};
|
||||
|
||||
#define I915_RESET_TIMEOUT (10 * HZ) /* 10s */
|
||||
#define I915_FENCE_TIMEOUT (10 * HZ) /* 10s */
|
||||
|
||||
@@ -1519,7 +1568,7 @@ struct i915_gpu_error {
|
||||
/* For reset and error_state handling. */
|
||||
spinlock_t lock;
|
||||
/* Protected by the above dev->gpu_error.lock. */
|
||||
struct drm_i915_error_state *first_error;
|
||||
struct i915_gpu_state *first_error;
|
||||
|
||||
unsigned long missed_irq_rings;
|
||||
|
||||
@@ -2053,6 +2102,10 @@ struct i915_oa_ops {
|
||||
bool (*oa_buffer_is_empty)(struct drm_i915_private *dev_priv);
|
||||
};
|
||||
|
||||
struct intel_cdclk_state {
|
||||
unsigned int cdclk, vco, ref;
|
||||
};
|
||||
|
||||
struct drm_i915_private {
|
||||
struct drm_device drm;
|
||||
|
||||
@@ -2063,8 +2116,6 @@ struct drm_i915_private {
|
||||
|
||||
const struct intel_device_info info;
|
||||
|
||||
int relative_constants_mode;
|
||||
|
||||
void __iomem *regs;
|
||||
|
||||
struct intel_uncore uncore;
|
||||
@@ -2157,13 +2208,7 @@ struct drm_i915_private {
|
||||
|
||||
unsigned int fsb_freq, mem_freq, is_ddr3;
|
||||
unsigned int skl_preferred_vco_freq;
|
||||
unsigned int cdclk_freq, max_cdclk_freq;
|
||||
|
||||
/*
|
||||
* For reading holding any crtc lock is sufficient,
|
||||
* for writing must hold all of them.
|
||||
*/
|
||||
unsigned int atomic_cdclk_freq;
|
||||
unsigned int max_cdclk_freq;
|
||||
|
||||
unsigned int max_dotclk_freq;
|
||||
unsigned int rawclk_freq;
|
||||
@@ -2171,8 +2216,22 @@ struct drm_i915_private {
|
||||
unsigned int czclk_freq;
|
||||
|
||||
struct {
|
||||
unsigned int vco, ref;
|
||||
} cdclk_pll;
|
||||
/*
|
||||
* The current logical cdclk state.
|
||||
* See intel_atomic_state.cdclk.logical
|
||||
*
|
||||
* For reading holding any crtc lock is sufficient,
|
||||
* for writing must hold all of them.
|
||||
*/
|
||||
struct intel_cdclk_state logical;
|
||||
/*
|
||||
* The current actual cdclk state.
|
||||
* See intel_atomic_state.cdclk.actual
|
||||
*/
|
||||
struct intel_cdclk_state actual;
|
||||
/* The current hardware cdclk state */
|
||||
struct intel_cdclk_state hw;
|
||||
} cdclk;
|
||||
|
||||
/**
|
||||
* wq - Driver workqueue for GEM.
|
||||
@@ -2752,6 +2811,12 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define IS_KBL_REVID(dev_priv, since, until) \
|
||||
(IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until))
|
||||
|
||||
#define GLK_REVID_A0 0x0
|
||||
#define GLK_REVID_A1 0x1
|
||||
|
||||
#define IS_GLK_REVID(dev_priv, since, until) \
|
||||
(IS_GEMINILAKE(dev_priv) && IS_REVID(dev_priv, since, until))
|
||||
|
||||
/*
|
||||
* The genX designation typically refers to the render engine, so render
|
||||
* capability related checks should use IS_GEN, while display and other checks
|
||||
@@ -2767,8 +2832,9 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
#define IS_GEN8(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(7)))
|
||||
#define IS_GEN9(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(8)))
|
||||
|
||||
#define IS_GEN9_LP(dev_priv) (IS_GEN9(dev_priv) && INTEL_INFO(dev_priv)->is_lp)
|
||||
#define IS_LP(dev_priv) (INTEL_INFO(dev_priv)->is_lp)
|
||||
#define IS_GEN9_LP(dev_priv) (IS_GEN9(dev_priv) && IS_LP(dev_priv))
|
||||
#define IS_GEN9_BC(dev_priv) (IS_GEN9(dev_priv) && !IS_LP(dev_priv))
|
||||
|
||||
#define ENGINE_MASK(id) BIT(id)
|
||||
#define RENDER_RING ENGINE_MASK(RCS)
|
||||
@@ -2810,9 +2876,7 @@ intel_info(const struct drm_i915_private *dev_priv)
|
||||
|
||||
/* WaRsDisableCoarsePowerGating:skl,bxt */
|
||||
#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
|
||||
(IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) || \
|
||||
IS_SKL_GT3(dev_priv) || \
|
||||
IS_SKL_GT4(dev_priv))
|
||||
(IS_SKL_GT3(dev_priv) || IS_SKL_GT4(dev_priv))
|
||||
|
||||
/*
|
||||
* dp aux and gmbus irq on gen4 seems to be able to generate legacy interrupts
|
||||
@@ -2952,6 +3016,9 @@ extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
|
||||
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
|
||||
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
|
||||
|
||||
int intel_engines_init_early(struct drm_i915_private *dev_priv);
|
||||
int intel_engines_init(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* intel_hotplug.c */
|
||||
void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
||||
u32 pin_mask, u32 long_mask);
|
||||
@@ -3129,6 +3196,7 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
void i915_gem_sanitize(struct drm_i915_private *i915);
|
||||
int i915_gem_load_init(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_load_cleanup(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
|
||||
@@ -3341,15 +3409,17 @@ static inline u32 i915_reset_count(struct i915_gpu_error *error)
|
||||
}
|
||||
|
||||
int i915_gem_reset_prepare(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_reset(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_reset_finish(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
|
||||
|
||||
void i915_gem_init_mmio(struct drm_i915_private *i915);
|
||||
int __must_check i915_gem_init(struct drm_i915_private *dev_priv);
|
||||
int __must_check i915_gem_init_hw(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_init_swizzling(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_cleanup_engines(struct drm_i915_private *dev_priv);
|
||||
int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
|
||||
unsigned int flags);
|
||||
int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
|
||||
unsigned int flags);
|
||||
int __must_check i915_gem_suspend(struct drm_i915_private *dev_priv);
|
||||
void i915_gem_resume(struct drm_i915_private *dev_priv);
|
||||
int i915_gem_fault(struct vm_fault *vmf);
|
||||
@@ -3543,7 +3613,7 @@ static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
|
||||
__printf(2, 3)
|
||||
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
|
||||
int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
|
||||
const struct i915_error_state_file_priv *error);
|
||||
const struct i915_gpu_state *gpu);
|
||||
int i915_error_state_buf_init(struct drm_i915_error_state_buf *eb,
|
||||
struct drm_i915_private *i915,
|
||||
size_t count, loff_t pos);
|
||||
@@ -3552,13 +3622,28 @@ static inline void i915_error_state_buf_release(
|
||||
{
|
||||
kfree(eb->buf);
|
||||
}
|
||||
|
||||
struct i915_gpu_state *i915_capture_gpu_state(struct drm_i915_private *i915);
|
||||
void i915_capture_error_state(struct drm_i915_private *dev_priv,
|
||||
u32 engine_mask,
|
||||
const char *error_msg);
|
||||
void i915_error_state_get(struct drm_device *dev,
|
||||
struct i915_error_state_file_priv *error_priv);
|
||||
void i915_error_state_put(struct i915_error_state_file_priv *error_priv);
|
||||
void i915_destroy_error_state(struct drm_i915_private *dev_priv);
|
||||
|
||||
static inline struct i915_gpu_state *
|
||||
i915_gpu_state_get(struct i915_gpu_state *gpu)
|
||||
{
|
||||
kref_get(&gpu->ref);
|
||||
return gpu;
|
||||
}
|
||||
|
||||
void __i915_gpu_state_free(struct kref *kref);
|
||||
static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
|
||||
{
|
||||
if (gpu)
|
||||
kref_put(&gpu->ref, __i915_gpu_state_free);
|
||||
}
|
||||
|
||||
struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915);
|
||||
void i915_reset_error_state(struct drm_i915_private *i915);
|
||||
|
||||
#else
|
||||
|
||||
@@ -3568,7 +3653,13 @@ static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
}
|
||||
|
||||
static inline void i915_destroy_error_state(struct drm_i915_private *dev_priv)
|
||||
static inline struct i915_gpu_state *
|
||||
i915_first_error_state(struct drm_i915_private *i915)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void i915_reset_error_state(struct drm_i915_private *i915)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3708,7 +3799,7 @@ extern void i915_redisable_vga(struct drm_i915_private *dev_priv);
|
||||
extern void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv);
|
||||
extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val);
|
||||
extern void intel_init_pch_refclk(struct drm_i915_private *dev_priv);
|
||||
extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
|
||||
extern int intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
|
||||
extern bool intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
|
||||
bool enable);
|
||||
|
||||
@@ -3724,7 +3815,6 @@ extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
|
||||
extern struct intel_display_error_state *
|
||||
intel_display_capture_error_state(struct drm_i915_private *dev_priv);
|
||||
extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
|
||||
struct drm_i915_private *dev_priv,
|
||||
struct intel_display_error_state *error);
|
||||
|
||||
int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val);
|
||||
@@ -3734,7 +3824,7 @@ int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
|
||||
|
||||
/* intel_sideband.c */
|
||||
u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr);
|
||||
void vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val);
|
||||
int vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val);
|
||||
u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
|
||||
u32 vlv_iosf_sb_read(struct drm_i915_private *dev_priv, u8 port, u32 reg);
|
||||
void vlv_iosf_sb_write(struct drm_i915_private *dev_priv, u8 port, u32 reg, u32 val);
|
||||
@@ -3953,14 +4043,34 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
__i915_request_irq_complete(struct drm_i915_gem_request *req)
|
||||
__i915_request_irq_complete(const struct drm_i915_gem_request *req)
|
||||
{
|
||||
struct intel_engine_cs *engine = req->engine;
|
||||
u32 seqno;
|
||||
|
||||
/* Note that the engine may have wrapped around the seqno, and
|
||||
* so our request->global_seqno will be ahead of the hardware,
|
||||
* even though it completed the request before wrapping. We catch
|
||||
* this by kicking all the waiters before resetting the seqno
|
||||
* in hardware, and also signal the fence.
|
||||
*/
|
||||
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &req->fence.flags))
|
||||
return true;
|
||||
|
||||
/* The request was dequeued before we were awoken. We check after
|
||||
* inspecting the hw to confirm that this was the same request
|
||||
* that generated the HWS update. The memory barriers within
|
||||
* the request execution are sufficient to ensure that a check
|
||||
* after reading the value from hw matches this request.
|
||||
*/
|
||||
seqno = i915_gem_request_global_seqno(req);
|
||||
if (!seqno)
|
||||
return false;
|
||||
|
||||
/* Before we do the heavier coherent read of the seqno,
|
||||
* check the value (hopefully) in the CPU cacheline.
|
||||
*/
|
||||
if (__i915_gem_request_completed(req))
|
||||
if (__i915_gem_request_completed(req, seqno))
|
||||
return true;
|
||||
|
||||
/* Ensure our read of the seqno is coherent so that we
|
||||
@@ -3975,9 +4085,9 @@ __i915_request_irq_complete(struct drm_i915_gem_request *req)
|
||||
* is woken.
|
||||
*/
|
||||
if (engine->irq_seqno_barrier &&
|
||||
rcu_access_pointer(engine->breadcrumbs.irq_seqno_bh) == current &&
|
||||
cmpxchg_relaxed(&engine->breadcrumbs.irq_posted, 1, 0)) {
|
||||
struct task_struct *tsk;
|
||||
test_and_clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted)) {
|
||||
struct intel_breadcrumbs *b = &engine->breadcrumbs;
|
||||
unsigned long flags;
|
||||
|
||||
/* The ordering of irq_posted versus applying the barrier
|
||||
* is crucial. The clearing of the current irq_posted must
|
||||
@@ -3999,19 +4109,18 @@ __i915_request_irq_complete(struct drm_i915_gem_request *req)
|
||||
* the seqno before we believe it coherent since they see
|
||||
* irq_posted == false but we are still running).
|
||||
*/
|
||||
rcu_read_lock();
|
||||
tsk = rcu_dereference(engine->breadcrumbs.irq_seqno_bh);
|
||||
if (tsk && tsk != current)
|
||||
spin_lock_irqsave(&b->irq_lock, flags);
|
||||
if (b->irq_wait && b->irq_wait->tsk != current)
|
||||
/* Note that if the bottom-half is changed as we
|
||||
* are sending the wake-up, the new bottom-half will
|
||||
* be woken by whomever made the change. We only have
|
||||
* to worry about when we steal the irq-posted for
|
||||
* ourself.
|
||||
*/
|
||||
wake_up_process(tsk);
|
||||
rcu_read_unlock();
|
||||
wake_up_process(b->irq_wait->tsk);
|
||||
spin_unlock_irqrestore(&b->irq_lock, flags);
|
||||
|
||||
if (__i915_gem_request_completed(req))
|
||||
if (__i915_gem_request_completed(req, seqno))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4042,4 +4151,10 @@ int remap_io_mapping(struct vm_area_struct *vma,
|
||||
unsigned long addr, unsigned long pfn, unsigned long size,
|
||||
struct io_mapping *iomap);
|
||||
|
||||
static inline bool i915_gem_object_is_coherent(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
return (obj->cache_level != I915_CACHE_NONE ||
|
||||
HAS_LLC(to_i915(obj->base.dev)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+209
-154
File diff suppressed because it is too large
Load Diff
@@ -28,9 +28,18 @@
|
||||
#ifdef CONFIG_DRM_I915_DEBUG_GEM
|
||||
#define GEM_BUG_ON(expr) BUG_ON(expr)
|
||||
#define GEM_WARN_ON(expr) WARN_ON(expr)
|
||||
|
||||
#define GEM_DEBUG_DECL(var) var
|
||||
#define GEM_DEBUG_EXEC(expr) expr
|
||||
#define GEM_DEBUG_BUG_ON(expr) GEM_BUG_ON(expr)
|
||||
|
||||
#else
|
||||
#define GEM_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
|
||||
#define GEM_WARN_ON(expr) (BUILD_BUG_ON_INVALID(expr), 0)
|
||||
|
||||
#define GEM_DEBUG_DECL(var)
|
||||
#define GEM_DEBUG_EXEC(expr) do { } while (0)
|
||||
#define GEM_DEBUG_BUG_ON(expr)
|
||||
#endif
|
||||
|
||||
#define I915_NUM_ENGINES 5
|
||||
|
||||
@@ -122,9 +122,9 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool,
|
||||
|
||||
if (tmp->base.size >= size) {
|
||||
/* Clear the set of shared fences early */
|
||||
ww_mutex_lock(&tmp->resv->lock, NULL);
|
||||
reservation_object_lock(tmp->resv, NULL);
|
||||
reservation_object_add_excl_fence(tmp->resv, NULL);
|
||||
ww_mutex_unlock(&tmp->resv->lock);
|
||||
reservation_object_unlock(tmp->resv);
|
||||
|
||||
obj = tmp;
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "i915_gem_clflush.h"
|
||||
|
||||
static DEFINE_SPINLOCK(clflush_lock);
|
||||
static u64 clflush_context;
|
||||
|
||||
struct clflush {
|
||||
struct dma_fence dma; /* Must be first for dma_fence_free() */
|
||||
struct i915_sw_fence wait;
|
||||
struct work_struct work;
|
||||
struct drm_i915_gem_object *obj;
|
||||
};
|
||||
|
||||
static const char *i915_clflush_get_driver_name(struct dma_fence *fence)
|
||||
{
|
||||
return DRIVER_NAME;
|
||||
}
|
||||
|
||||
static const char *i915_clflush_get_timeline_name(struct dma_fence *fence)
|
||||
{
|
||||
return "clflush";
|
||||
}
|
||||
|
||||
static bool i915_clflush_enable_signaling(struct dma_fence *fence)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void i915_clflush_release(struct dma_fence *fence)
|
||||
{
|
||||
struct clflush *clflush = container_of(fence, typeof(*clflush), dma);
|
||||
|
||||
i915_sw_fence_fini(&clflush->wait);
|
||||
|
||||
BUILD_BUG_ON(offsetof(typeof(*clflush), dma));
|
||||
dma_fence_free(&clflush->dma);
|
||||
}
|
||||
|
||||
static const struct dma_fence_ops i915_clflush_ops = {
|
||||
.get_driver_name = i915_clflush_get_driver_name,
|
||||
.get_timeline_name = i915_clflush_get_timeline_name,
|
||||
.enable_signaling = i915_clflush_enable_signaling,
|
||||
.wait = dma_fence_default_wait,
|
||||
.release = i915_clflush_release,
|
||||
};
|
||||
|
||||
static void __i915_do_clflush(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
drm_clflush_sg(obj->mm.pages);
|
||||
obj->cache_dirty = false;
|
||||
|
||||
intel_fb_obj_flush(obj, ORIGIN_CPU);
|
||||
}
|
||||
|
||||
static void i915_clflush_work(struct work_struct *work)
|
||||
{
|
||||
struct clflush *clflush = container_of(work, typeof(*clflush), work);
|
||||
struct drm_i915_gem_object *obj = clflush->obj;
|
||||
|
||||
if (!obj->cache_dirty)
|
||||
goto out;
|
||||
|
||||
if (i915_gem_object_pin_pages(obj)) {
|
||||
DRM_ERROR("Failed to acquire obj->pages for clflushing\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
__i915_do_clflush(obj);
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
|
||||
out:
|
||||
i915_gem_object_put(obj);
|
||||
|
||||
dma_fence_signal(&clflush->dma);
|
||||
dma_fence_put(&clflush->dma);
|
||||
}
|
||||
|
||||
static int __i915_sw_fence_call
|
||||
i915_clflush_notify(struct i915_sw_fence *fence,
|
||||
enum i915_sw_fence_notify state)
|
||||
{
|
||||
struct clflush *clflush = container_of(fence, typeof(*clflush), wait);
|
||||
|
||||
switch (state) {
|
||||
case FENCE_COMPLETE:
|
||||
schedule_work(&clflush->work);
|
||||
break;
|
||||
|
||||
case FENCE_FREE:
|
||||
dma_fence_put(&clflush->dma);
|
||||
break;
|
||||
}
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
void i915_gem_clflush_object(struct drm_i915_gem_object *obj,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct clflush *clflush;
|
||||
|
||||
/*
|
||||
* Stolen memory is always coherent with the GPU as it is explicitly
|
||||
* marked as wc by the system, or the system is cache-coherent.
|
||||
* Similarly, we only access struct pages through the CPU cache, so
|
||||
* anything not backed by physical memory we consider to be always
|
||||
* coherent and not need clflushing.
|
||||
*/
|
||||
if (!i915_gem_object_has_struct_page(obj))
|
||||
return;
|
||||
|
||||
obj->cache_dirty = true;
|
||||
|
||||
/* If the GPU is snooping the contents of the CPU cache,
|
||||
* we do not need to manually clear the CPU cache lines. However,
|
||||
* the caches are only snooped when the render cache is
|
||||
* flushed/invalidated. As we always have to emit invalidations
|
||||
* and flushes when moving into and out of the RENDER domain, correct
|
||||
* snooping behaviour occurs naturally as the result of our domain
|
||||
* tracking.
|
||||
*/
|
||||
if (!(flags & I915_CLFLUSH_FORCE) && i915_gem_object_is_coherent(obj))
|
||||
return;
|
||||
|
||||
trace_i915_gem_object_clflush(obj);
|
||||
|
||||
clflush = NULL;
|
||||
if (!(flags & I915_CLFLUSH_SYNC))
|
||||
clflush = kmalloc(sizeof(*clflush), GFP_KERNEL);
|
||||
if (clflush) {
|
||||
dma_fence_init(&clflush->dma,
|
||||
&i915_clflush_ops,
|
||||
&clflush_lock,
|
||||
clflush_context,
|
||||
0);
|
||||
i915_sw_fence_init(&clflush->wait, i915_clflush_notify);
|
||||
|
||||
clflush->obj = i915_gem_object_get(obj);
|
||||
INIT_WORK(&clflush->work, i915_clflush_work);
|
||||
|
||||
dma_fence_get(&clflush->dma);
|
||||
|
||||
i915_sw_fence_await_reservation(&clflush->wait,
|
||||
obj->resv, NULL,
|
||||
false, I915_FENCE_TIMEOUT,
|
||||
GFP_KERNEL);
|
||||
|
||||
reservation_object_lock(obj->resv, NULL);
|
||||
reservation_object_add_excl_fence(obj->resv, &clflush->dma);
|
||||
reservation_object_unlock(obj->resv);
|
||||
|
||||
i915_sw_fence_commit(&clflush->wait);
|
||||
} else if (obj->mm.pages) {
|
||||
__i915_do_clflush(obj);
|
||||
} else {
|
||||
GEM_BUG_ON(obj->base.write_domain != I915_GEM_DOMAIN_CPU);
|
||||
}
|
||||
}
|
||||
|
||||
void i915_gem_clflush_init(struct drm_i915_private *i915)
|
||||
{
|
||||
clflush_context = dma_fence_context_alloc(1);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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_GEM_CLFLUSH_H__
|
||||
#define __I915_GEM_CLFLUSH_H__
|
||||
|
||||
struct drm_i915_private;
|
||||
struct drm_i915_gem_object;
|
||||
|
||||
void i915_gem_clflush_init(struct drm_i915_private *i915);
|
||||
void i915_gem_clflush_object(struct drm_i915_gem_object *obj,
|
||||
unsigned int flags);
|
||||
#define I915_CLFLUSH_FORCE BIT(0)
|
||||
#define I915_CLFLUSH_SYNC BIT(1)
|
||||
|
||||
#endif /* __I915_GEM_CLFLUSH_H__ */
|
||||
@@ -92,21 +92,6 @@
|
||||
|
||||
#define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1
|
||||
|
||||
/* This is a HW constraint. The value below is the largest known requirement
|
||||
* I've seen in a spec to date, and that was a workaround for a non-shipping
|
||||
* part. It should be safe to decrease this, but it's more future proof as is.
|
||||
*/
|
||||
#define GEN6_CONTEXT_ALIGN (64<<10)
|
||||
#define GEN7_CONTEXT_ALIGN I915_GTT_MIN_ALIGNMENT
|
||||
|
||||
static size_t get_context_alignment(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_GEN6(dev_priv))
|
||||
return GEN6_CONTEXT_ALIGN;
|
||||
|
||||
return GEN7_CONTEXT_ALIGN;
|
||||
}
|
||||
|
||||
static int get_context_size(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
int ret;
|
||||
@@ -236,6 +221,30 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 default_desc_template(const struct drm_i915_private *i915,
|
||||
const struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
u32 address_mode;
|
||||
u32 desc;
|
||||
|
||||
desc = GEN8_CTX_VALID | GEN8_CTX_PRIVILEGE;
|
||||
|
||||
address_mode = INTEL_LEGACY_32B_CONTEXT;
|
||||
if (ppgtt && i915_vm_is_48bit(&ppgtt->base))
|
||||
address_mode = INTEL_LEGACY_64B_CONTEXT;
|
||||
desc |= address_mode << GEN8_CTX_ADDRESSING_MODE_SHIFT;
|
||||
|
||||
if (IS_GEN8(i915))
|
||||
desc |= GEN8_CTX_L3LLC_COHERENT;
|
||||
|
||||
/* TODO: WaDisableLiteRestore when we start using semaphore
|
||||
* signalling between Command Streamers
|
||||
* ring->ctx_desc_template |= GEN8_CTX_FORCE_RESTORE;
|
||||
*/
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
static struct i915_gem_context *
|
||||
__create_hw_context(struct drm_i915_private *dev_priv,
|
||||
struct drm_i915_file_private *file_priv)
|
||||
@@ -257,8 +266,6 @@ __create_hw_context(struct drm_i915_private *dev_priv,
|
||||
list_add_tail(&ctx->link, &dev_priv->context_list);
|
||||
ctx->i915 = dev_priv;
|
||||
|
||||
ctx->ggtt_alignment = get_context_alignment(dev_priv);
|
||||
|
||||
if (dev_priv->hw_context_size) {
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_vma *vma;
|
||||
@@ -309,8 +316,8 @@ __create_hw_context(struct drm_i915_private *dev_priv,
|
||||
|
||||
i915_gem_context_set_bannable(ctx);
|
||||
ctx->ring_size = 4 * PAGE_SIZE;
|
||||
ctx->desc_template = GEN8_CTX_ADDRESSING_MODE(dev_priv) <<
|
||||
GEN8_CTX_ADDRESSING_MODE_SHIFT;
|
||||
ctx->desc_template =
|
||||
default_desc_template(dev_priv, dev_priv->mm.aliasing_ppgtt);
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&ctx->status_notifier);
|
||||
|
||||
/* GuC requires the ring to be placed above GUC_WOPCM_TOP. If GuC is not
|
||||
@@ -332,6 +339,13 @@ err_out:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void __destroy_hw_context(struct i915_gem_context *ctx,
|
||||
struct drm_i915_file_private *file_priv)
|
||||
{
|
||||
idr_remove(&file_priv->context_idr, ctx->user_handle);
|
||||
context_close(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default context needs to exist per ring that uses contexts. It stores the
|
||||
* context state of the GPU for applications that don't utilize HW contexts, as
|
||||
@@ -356,12 +370,12 @@ i915_gem_create_context(struct drm_i915_private *dev_priv,
|
||||
if (IS_ERR(ppgtt)) {
|
||||
DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
|
||||
PTR_ERR(ppgtt));
|
||||
idr_remove(&file_priv->context_idr, ctx->user_handle);
|
||||
context_close(ctx);
|
||||
__destroy_hw_context(ctx, file_priv);
|
||||
return ERR_CAST(ppgtt);
|
||||
}
|
||||
|
||||
ctx->ppgtt = ppgtt;
|
||||
ctx->desc_template = default_desc_template(dev_priv, ppgtt);
|
||||
}
|
||||
|
||||
trace_i915_context_create(ctx);
|
||||
@@ -400,7 +414,8 @@ i915_gem_context_create_gvt(struct drm_device *dev)
|
||||
i915_gem_context_set_closed(ctx); /* not user accessible */
|
||||
i915_gem_context_clear_bannable(ctx);
|
||||
i915_gem_context_set_force_single_submission(ctx);
|
||||
ctx->ring_size = 512 * PAGE_SIZE; /* Max ring buffer size */
|
||||
if (!i915.enable_guc_submission)
|
||||
ctx->ring_size = 512 * PAGE_SIZE; /* Max ring buffer size */
|
||||
|
||||
GEM_BUG_ON(i915_gem_context_is_kernel(ctx));
|
||||
out:
|
||||
@@ -451,6 +466,11 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv)
|
||||
return PTR_ERR(ctx);
|
||||
}
|
||||
|
||||
/* For easy recognisablity, we want the kernel context to be 0 and then
|
||||
* all user contexts will have non-zero hw_id.
|
||||
*/
|
||||
GEM_BUG_ON(ctx->hw_id);
|
||||
|
||||
i915_gem_context_clear_bannable(ctx);
|
||||
ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */
|
||||
dev_priv->kernel_context = ctx;
|
||||
@@ -560,27 +580,15 @@ static inline int
|
||||
mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = req->i915;
|
||||
struct intel_ring *ring = req->ring;
|
||||
struct intel_engine_cs *engine = req->engine;
|
||||
enum intel_engine_id id;
|
||||
u32 flags = hw_flags | MI_MM_SPACE_GTT;
|
||||
u32 *cs, flags = hw_flags | MI_MM_SPACE_GTT;
|
||||
const int num_rings =
|
||||
/* Use an extended w/a on ivb+ if signalling from other rings */
|
||||
i915.semaphores ?
|
||||
INTEL_INFO(dev_priv)->num_rings - 1 :
|
||||
0;
|
||||
int len, ret;
|
||||
|
||||
/* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
|
||||
* invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
|
||||
* explicitly, so we rely on the value at ring init, stored in
|
||||
* itlb_before_ctx_switch.
|
||||
*/
|
||||
if (IS_GEN6(dev_priv)) {
|
||||
ret = engine->emit_flush(req, EMIT_INVALIDATE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
int len;
|
||||
|
||||
/* These flags are for resource streamer on HSW+ */
|
||||
if (IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8)
|
||||
@@ -593,99 +601,92 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
|
||||
if (INTEL_GEN(dev_priv) >= 7)
|
||||
len += 2 + (num_rings ? 4*num_rings + 6 : 0);
|
||||
|
||||
ret = intel_ring_begin(req, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
cs = intel_ring_begin(req, len);
|
||||
if (IS_ERR(cs))
|
||||
return PTR_ERR(cs);
|
||||
|
||||
/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */
|
||||
if (INTEL_GEN(dev_priv) >= 7) {
|
||||
intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
|
||||
*cs++ = MI_ARB_ON_OFF | MI_ARB_DISABLE;
|
||||
if (num_rings) {
|
||||
struct intel_engine_cs *signaller;
|
||||
|
||||
intel_ring_emit(ring,
|
||||
MI_LOAD_REGISTER_IMM(num_rings));
|
||||
*cs++ = MI_LOAD_REGISTER_IMM(num_rings);
|
||||
for_each_engine(signaller, dev_priv, id) {
|
||||
if (signaller == engine)
|
||||
continue;
|
||||
|
||||
intel_ring_emit_reg(ring,
|
||||
RING_PSMI_CTL(signaller->mmio_base));
|
||||
intel_ring_emit(ring,
|
||||
_MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
|
||||
*cs++ = i915_mmio_reg_offset(
|
||||
RING_PSMI_CTL(signaller->mmio_base));
|
||||
*cs++ = _MASKED_BIT_ENABLE(
|
||||
GEN6_PSMI_SLEEP_MSG_DISABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_SET_CONTEXT);
|
||||
intel_ring_emit(ring,
|
||||
i915_ggtt_offset(req->ctx->engine[RCS].state) | flags);
|
||||
*cs++ = MI_NOOP;
|
||||
*cs++ = MI_SET_CONTEXT;
|
||||
*cs++ = i915_ggtt_offset(req->ctx->engine[RCS].state) | flags;
|
||||
/*
|
||||
* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
|
||||
* WaMiSetContext_Hang:snb,ivb,vlv
|
||||
*/
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
*cs++ = MI_NOOP;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 7) {
|
||||
if (num_rings) {
|
||||
struct intel_engine_cs *signaller;
|
||||
i915_reg_t last_reg = {}; /* keep gcc quiet */
|
||||
|
||||
intel_ring_emit(ring,
|
||||
MI_LOAD_REGISTER_IMM(num_rings));
|
||||
*cs++ = MI_LOAD_REGISTER_IMM(num_rings);
|
||||
for_each_engine(signaller, dev_priv, id) {
|
||||
if (signaller == engine)
|
||||
continue;
|
||||
|
||||
last_reg = RING_PSMI_CTL(signaller->mmio_base);
|
||||
intel_ring_emit_reg(ring, last_reg);
|
||||
intel_ring_emit(ring,
|
||||
_MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
|
||||
*cs++ = i915_mmio_reg_offset(last_reg);
|
||||
*cs++ = _MASKED_BIT_DISABLE(
|
||||
GEN6_PSMI_SLEEP_MSG_DISABLE);
|
||||
}
|
||||
|
||||
/* Insert a delay before the next switch! */
|
||||
intel_ring_emit(ring,
|
||||
MI_STORE_REGISTER_MEM |
|
||||
MI_SRM_LRM_GLOBAL_GTT);
|
||||
intel_ring_emit_reg(ring, last_reg);
|
||||
intel_ring_emit(ring,
|
||||
i915_ggtt_offset(engine->scratch));
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
*cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
|
||||
*cs++ = i915_mmio_reg_offset(last_reg);
|
||||
*cs++ = i915_ggtt_offset(engine->scratch);
|
||||
*cs++ = MI_NOOP;
|
||||
}
|
||||
intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE);
|
||||
*cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE;
|
||||
}
|
||||
|
||||
intel_ring_advance(ring);
|
||||
intel_ring_advance(req, cs);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int remap_l3(struct drm_i915_gem_request *req, int slice)
|
||||
{
|
||||
u32 *remap_info = req->i915->l3_parity.remap_info[slice];
|
||||
struct intel_ring *ring = req->ring;
|
||||
int i, ret;
|
||||
u32 *cs, *remap_info = req->i915->l3_parity.remap_info[slice];
|
||||
int i;
|
||||
|
||||
if (!remap_info)
|
||||
return 0;
|
||||
|
||||
ret = intel_ring_begin(req, GEN7_L3LOG_SIZE/4 * 2 + 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
cs = intel_ring_begin(req, GEN7_L3LOG_SIZE/4 * 2 + 2);
|
||||
if (IS_ERR(cs))
|
||||
return PTR_ERR(cs);
|
||||
|
||||
/*
|
||||
* Note: We do not worry about the concurrent register cacheline hang
|
||||
* here because no other code should access these registers other than
|
||||
* at initialization time.
|
||||
*/
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(GEN7_L3LOG_SIZE/4));
|
||||
*cs++ = MI_LOAD_REGISTER_IMM(GEN7_L3LOG_SIZE/4);
|
||||
for (i = 0; i < GEN7_L3LOG_SIZE/4; i++) {
|
||||
intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i));
|
||||
intel_ring_emit(ring, remap_info[i]);
|
||||
*cs++ = i915_mmio_reg_offset(GEN7_L3LOG(slice, i));
|
||||
*cs++ = remap_info[i];
|
||||
}
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_advance(ring);
|
||||
*cs++ = MI_NOOP;
|
||||
intel_ring_advance(req, cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1014,8 +1015,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
return PTR_ERR(ctx);
|
||||
}
|
||||
|
||||
idr_remove(&file_priv->context_idr, ctx->user_handle);
|
||||
context_close(ctx);
|
||||
__destroy_hw_context(ctx, file_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG("HW context %d destroyed\n", args->ctx_id);
|
||||
@@ -1164,3 +1164,8 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
#include "selftests/mock_context.c"
|
||||
#include "selftests/i915_gem_context.c"
|
||||
#endif
|
||||
|
||||
@@ -140,8 +140,6 @@ struct i915_gem_context {
|
||||
*/
|
||||
int priority;
|
||||
|
||||
/** ggtt_alignment: alignment restriction for context objects */
|
||||
u32 ggtt_alignment;
|
||||
/** ggtt_offset_bias: placement restriction for context objects */
|
||||
u32 ggtt_offset_bias;
|
||||
|
||||
|
||||
@@ -307,3 +307,8 @@ fail_detach:
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
#include "selftests/mock_dmabuf.c"
|
||||
#include "selftests/i915_gem_dmabuf.c"
|
||||
#endif
|
||||
|
||||
@@ -258,6 +258,9 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&vm->i915->drm.struct_mutex);
|
||||
GEM_BUG_ON(!IS_ALIGNED(start, I915_GTT_PAGE_SIZE));
|
||||
GEM_BUG_ON(!IS_ALIGNED(end, I915_GTT_PAGE_SIZE));
|
||||
|
||||
trace_i915_gem_evict_node(vm, target, flags);
|
||||
|
||||
/* Retire before we search the active list. Although we have
|
||||
@@ -271,11 +274,13 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
|
||||
check_color = vm->mm.color_adjust;
|
||||
if (check_color) {
|
||||
/* Expand search to cover neighbouring guard pages (or lack!) */
|
||||
if (start > vm->start)
|
||||
if (start)
|
||||
start -= I915_GTT_PAGE_SIZE;
|
||||
if (end < vm->start + vm->total)
|
||||
end += I915_GTT_PAGE_SIZE;
|
||||
|
||||
/* Always look at the page afterwards to avoid the end-of-GTT */
|
||||
end += I915_GTT_PAGE_SIZE;
|
||||
}
|
||||
GEM_BUG_ON(start >= end);
|
||||
|
||||
drm_mm_for_each_node_in_range(node, &vm->mm, start, end) {
|
||||
/* If we find any non-objects (!vma), we cannot evict them */
|
||||
@@ -284,6 +289,7 @@ int i915_gem_evict_for_node(struct i915_address_space *vm,
|
||||
break;
|
||||
}
|
||||
|
||||
GEM_BUG_ON(!node->allocated);
|
||||
vma = container_of(node, typeof(*vma), node);
|
||||
|
||||
/* If we are using coloring to insert guard pages between
|
||||
@@ -387,3 +393,7 @@ int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
|
||||
#include "selftests/i915_gem_evict.c"
|
||||
#endif
|
||||
|
||||
@@ -28,12 +28,14 @@
|
||||
|
||||
#include <linux/dma_remapping.h>
|
||||
#include <linux/reservation.h>
|
||||
#include <linux/sync_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_gem_clflush.h"
|
||||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
@@ -1110,13 +1112,18 @@ i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
|
||||
list_for_each_entry(vma, vmas, exec_list) {
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
|
||||
if (vma->exec_entry->flags & EXEC_OBJECT_ASYNC)
|
||||
continue;
|
||||
|
||||
if (obj->base.write_domain & I915_GEM_DOMAIN_CPU) {
|
||||
i915_gem_clflush_object(obj, 0);
|
||||
obj->base.write_domain = 0;
|
||||
}
|
||||
|
||||
ret = i915_gem_request_await_object
|
||||
(req, obj, obj->base.pending_write_domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)
|
||||
i915_gem_clflush_object(obj, false);
|
||||
}
|
||||
|
||||
/* Unconditionally flush any chipset caches (for streaming writes). */
|
||||
@@ -1297,12 +1304,12 @@ static void eb_export_fence(struct drm_i915_gem_object *obj,
|
||||
* handle an error right now. Worst case should be missed
|
||||
* synchronisation leading to rendering corruption.
|
||||
*/
|
||||
ww_mutex_lock(&resv->lock, NULL);
|
||||
reservation_object_lock(resv, NULL);
|
||||
if (flags & EXEC_OBJECT_WRITE)
|
||||
reservation_object_add_excl_fence(resv, &req->fence);
|
||||
else if (reservation_object_reserve_shared(resv) == 0)
|
||||
reservation_object_add_shared_fence(resv, &req->fence);
|
||||
ww_mutex_unlock(&resv->lock);
|
||||
reservation_object_unlock(resv);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1313,8 +1320,6 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
|
||||
|
||||
list_for_each_entry(vma, vmas, exec_list) {
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
u32 old_read = obj->base.read_domains;
|
||||
u32 old_write = obj->base.write_domain;
|
||||
|
||||
obj->base.write_domain = obj->base.pending_write_domain;
|
||||
if (obj->base.write_domain)
|
||||
@@ -1325,32 +1330,31 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas,
|
||||
|
||||
i915_vma_move_to_active(vma, req, vma->exec_entry->flags);
|
||||
eb_export_fence(obj, req, vma->exec_entry->flags);
|
||||
trace_i915_gem_object_change_domain(obj, old_read, old_write);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
i915_reset_gen7_sol_offsets(struct drm_i915_gem_request *req)
|
||||
{
|
||||
struct intel_ring *ring = req->ring;
|
||||
int ret, i;
|
||||
u32 *cs;
|
||||
int i;
|
||||
|
||||
if (!IS_GEN7(req->i915) || req->engine->id != RCS) {
|
||||
DRM_DEBUG("sol reset is gen7/rcs only\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = intel_ring_begin(req, 4 * 3);
|
||||
if (ret)
|
||||
return ret;
|
||||
cs = intel_ring_begin(req, 4 * 3);
|
||||
if (IS_ERR(cs))
|
||||
return PTR_ERR(cs);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i));
|
||||
intel_ring_emit(ring, 0);
|
||||
*cs++ = MI_LOAD_REGISTER_IMM(1);
|
||||
*cs++ = i915_mmio_reg_offset(GEN7_SO_WRITE_OFFSET(i));
|
||||
*cs++ = 0;
|
||||
}
|
||||
|
||||
intel_ring_advance(ring);
|
||||
intel_ring_advance(req, cs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1403,15 +1407,20 @@ out:
|
||||
return vma;
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_client(struct drm_i915_gem_request *req,
|
||||
struct drm_file *file)
|
||||
{
|
||||
req->file_priv = file->driver_priv;
|
||||
list_add_tail(&req->client_link, &req->file_priv->mm.request_list);
|
||||
}
|
||||
|
||||
static int
|
||||
execbuf_submit(struct i915_execbuffer_params *params,
|
||||
struct drm_i915_gem_execbuffer2 *args,
|
||||
struct list_head *vmas)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = params->request->i915;
|
||||
u64 exec_start, exec_len;
|
||||
int instp_mode;
|
||||
u32 instp_mask;
|
||||
int ret;
|
||||
|
||||
ret = i915_gem_execbuffer_move_to_gpu(params->request, vmas);
|
||||
@@ -1422,56 +1431,11 @@ execbuf_submit(struct i915_execbuffer_params *params,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK;
|
||||
instp_mask = I915_EXEC_CONSTANTS_MASK;
|
||||
switch (instp_mode) {
|
||||
case I915_EXEC_CONSTANTS_REL_GENERAL:
|
||||
case I915_EXEC_CONSTANTS_ABSOLUTE:
|
||||
case I915_EXEC_CONSTANTS_REL_SURFACE:
|
||||
if (instp_mode != 0 && params->engine->id != RCS) {
|
||||
DRM_DEBUG("non-0 rel constants mode on non-RCS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (instp_mode != dev_priv->relative_constants_mode) {
|
||||
if (INTEL_INFO(dev_priv)->gen < 4) {
|
||||
DRM_DEBUG("no rel constants on pre-gen4\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (INTEL_INFO(dev_priv)->gen > 5 &&
|
||||
instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) {
|
||||
DRM_DEBUG("rel surface constants mode invalid on gen5+\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The HW changed the meaning on this bit on gen6 */
|
||||
if (INTEL_INFO(dev_priv)->gen >= 6)
|
||||
instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode);
|
||||
if (args->flags & I915_EXEC_CONSTANTS_MASK) {
|
||||
DRM_DEBUG("I915_EXEC_CONSTANTS_* unsupported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (params->engine->id == RCS &&
|
||||
instp_mode != dev_priv->relative_constants_mode) {
|
||||
struct intel_ring *ring = params->request->ring;
|
||||
|
||||
ret = intel_ring_begin(params->request, 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit_reg(ring, INSTPM);
|
||||
intel_ring_emit(ring, instp_mask << 16 | instp_mode);
|
||||
intel_ring_advance(ring);
|
||||
|
||||
dev_priv->relative_constants_mode = instp_mode;
|
||||
}
|
||||
|
||||
if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
|
||||
ret = i915_reset_gen7_sol_offsets(params->request);
|
||||
if (ret)
|
||||
@@ -1491,8 +1455,6 @@ execbuf_submit(struct i915_execbuffer_params *params,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
trace_i915_gem_ring_dispatch(params->request, params->dispatch_flags);
|
||||
|
||||
i915_gem_execbuffer_move_to_active(vmas, params->request);
|
||||
|
||||
return 0;
|
||||
@@ -1591,6 +1553,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
struct i915_execbuffer_params *params = ¶ms_master;
|
||||
const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
|
||||
u32 dispatch_flags;
|
||||
struct dma_fence *in_fence = NULL;
|
||||
struct sync_file *out_fence = NULL;
|
||||
int out_fence_fd = -1;
|
||||
int ret;
|
||||
bool need_relocs;
|
||||
|
||||
@@ -1634,6 +1599,20 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
dispatch_flags |= I915_DISPATCH_RS;
|
||||
}
|
||||
|
||||
if (args->flags & I915_EXEC_FENCE_IN) {
|
||||
in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2));
|
||||
if (!in_fence)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (args->flags & I915_EXEC_FENCE_OUT) {
|
||||
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
|
||||
if (out_fence_fd < 0) {
|
||||
ret = out_fence_fd;
|
||||
goto err_in_fence;
|
||||
}
|
||||
}
|
||||
|
||||
/* Take a local wakeref for preparing to dispatch the execbuf as
|
||||
* we expect to access the hardware fairly frequently in the
|
||||
* process. Upon first dispatch, we acquire another prolonged
|
||||
@@ -1778,6 +1757,21 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
goto err_batch_unpin;
|
||||
}
|
||||
|
||||
if (in_fence) {
|
||||
ret = i915_gem_request_await_dma_fence(params->request,
|
||||
in_fence);
|
||||
if (ret < 0)
|
||||
goto err_request;
|
||||
}
|
||||
|
||||
if (out_fence_fd != -1) {
|
||||
out_fence = sync_file_create(¶ms->request->fence);
|
||||
if (!out_fence) {
|
||||
ret = -ENOMEM;
|
||||
goto err_request;
|
||||
}
|
||||
}
|
||||
|
||||
/* Whilst this request exists, batch_obj will be on the
|
||||
* active_list, and so will hold the active reference. Only when this
|
||||
* request is retired will the the batch_obj be moved onto the
|
||||
@@ -1786,10 +1780,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
*/
|
||||
params->request->batch = params->batch;
|
||||
|
||||
ret = i915_gem_request_add_to_client(params->request, file);
|
||||
if (ret)
|
||||
goto err_request;
|
||||
|
||||
/*
|
||||
* Save assorted stuff away to pass through to *_submission().
|
||||
* NB: This data should be 'persistent' and not local as it will
|
||||
@@ -1802,9 +1792,23 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
params->dispatch_flags = dispatch_flags;
|
||||
params->ctx = ctx;
|
||||
|
||||
trace_i915_gem_request_queue(params->request, dispatch_flags);
|
||||
|
||||
ret = execbuf_submit(params, args, &eb->vmas);
|
||||
err_request:
|
||||
__i915_add_request(params->request, ret == 0);
|
||||
add_to_client(params->request, file);
|
||||
|
||||
if (out_fence) {
|
||||
if (ret == 0) {
|
||||
fd_install(out_fence_fd, out_fence->file);
|
||||
args->rsvd2 &= GENMASK_ULL(0, 31); /* keep in-fence */
|
||||
args->rsvd2 |= (u64)out_fence_fd << 32;
|
||||
out_fence_fd = -1;
|
||||
} else {
|
||||
fput(out_fence->file);
|
||||
}
|
||||
}
|
||||
|
||||
err_batch_unpin:
|
||||
/*
|
||||
@@ -1826,6 +1830,10 @@ pre_mutex_err:
|
||||
/* intel_gpu_busy should also get a ref, so it will free when the device
|
||||
* is really idle. */
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
if (out_fence_fd != -1)
|
||||
put_unused_fd(out_fence_fd);
|
||||
err_in_fence:
|
||||
dma_fence_put(in_fence);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1933,11 +1941,6 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (args->rsvd2 != 0) {
|
||||
DRM_DEBUG("dirty rvsd2 field\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
exec2_list = drm_malloc_gfp(args->buffer_count,
|
||||
sizeof(*exec2_list),
|
||||
GFP_TEMPORARY);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user