1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/drivers/gpu/drm/i915/gt/intel_engine_pool.c
Linus Torvalds a6ed68d646 drm main pull for 5.5-rc1
-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJd3YntAAoJEAx081l5xIa+dcQP/ikABkpm+q23FLKteRpL1rtX
 xqlg5+KHW+YVCDls2BrINF6vYzyisoa8fNPlKMmOHse/IgMhFe9vBbCj1KQQOUR1
 apNycI1wrcw/mn2WDikoIcF6C5cjqK9YVknnYoM6HnF1VmpGd1ecSGrOHrunEkrK
 cMAWYIeqWGU8Gj/HUOitAFpLWFUMNle0BJuRoGLcoMusgS8yuCIEcpNzRhgL8fvJ
 bW4imuyv24OjPoQzbKD0oQ0VIP86H0eM4LIeGZ2uyK/BSPKmMDqI4z4isUheS7RL
 w4a6BdobMIdhew5dBXS0LsUJ3JniVJdHy123q9KgpmQAhGpiNoLT6BujfoUTUeWx
 Mu0vM8Xmv9n4npdBYC+fLEFQXYJlu9uBA490jP84Kz6Fg1c6GyBebDY7/c2O4Zmg
 7pvygmUF6boD6v2sIC/3161crgwU4g8zoxm2V4i9naxes2QB13LiEuJWlaI/FdxY
 fd3zpglFGdoF1ThNne4QDh6gMKpXvjITyu/QxZeZ67Dt6i0Aqw9cRGHSpiVhYyDc
 cx2hAp+rDvUi5SHkJKFpVImjB2DDn2xUG2uFMHz0cy9wNg203L3fRDi0hVtnM1+W
 VpCxyLs2Upz6kEjDRVsfMZ9chCcWAWpVuKhtuuMUDw/IKnbP3uV8kzgJpVpaRVkD
 76s5uYWHHBlk1IVlkOUP
 =Hj7G
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2019-11-27' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "Lots of stuff in here, though it hasn't been too insane this merge
  apart from dealing with the security fun.

  uapi:
   - export different colorspace properties on DP vs HDMI
   - new fourcc for ARM 16x16 block format
   - syncobj: allow querying last submitted timeline value
   - DRM_FORMAT_BIG_ENDIAN defined as unsigned

  core:
   - allow using gem vma manager in ttm
   - connector/encoder/bridge doc fixes
   - allow more than 3 encoders for a connector
   - displayport mst suspend/resume reprobing support
   - vram lazy unmapping, uniform vram mm and gem vram
   - edid cleanups + AVI informframe bar info
   - displayport helpers - dpcd parser added

  dp_cec:
   - Allow a connector to be associated with a cec device

  ttm:
   - pipelining with no_gpu_wait fix
   - always keep BOs on the LRU

  sched:
   - allow free_job routine to sleep

  i915:
   - Block userptr from mappable GTT
   - i915 perf uapi versioning
   - OA stream dynamic reconfiguration
   - make context persistence optional
   - introduce DRM_I915_UNSTABLE Kconfig
   - add fake lmem testing under unstable
   - BT.2020 support for DP MSA
   - struct mutex elimination
   - Tigerlake display/PLL/power management improvements
   - Jasper Lake PCH support
   - refactor PMU for multiple GPUs
   - Icelake firmware update
   - Split out vga + switcheroo code

  amdgpu:
   - implement dma-buf import/export without helpers
   - vega20 RAS enablement
   - DC i2c over aux fixes
   - renoir GPU reset
   - DC HDCP support
   - BACO support for CI/VI asics
   - MSI-X support
   - Arcturus EEPROM support
   - Arcturus VCN encode support
   - VCN dynamic powergating on RV/RV2

  amdkfd:
   - add navi12/14/renoir support to kfd

  radeon:
   - SI dpm fix ported from amdgpu
   - fix bad DMA on ppc platforms

  gma500:
   - memory leak fixes

  qxl:
   - convert to new gem mmap

  exynos:
   - build warning fix

  komeda:
   - add aclk sysfs attribute

  v3d:
   - userspace cleanup uapi change

  i810:
   - fix for underflow in dispatch ioctls

  ast:
   - refactor show_cursor

  mgag200:
   - refactor show_cursor

  arcgpu:
   - encoder finding improvements

  mediatek:
   - mipi_tx, dsi and partial crtc support for MT8183 SoC
   - rotation support

  meson:
   - add suspend/resume support

  omap:
   - misc refactors

  tegra:
   - DisplayPort support for Tegra 210, 186 and 194.
   - IOMMU-backed DMA API fixes

  panfrost:
   - fix lockdep issue
   - simplify devfreq integration

  rcar-du:
   - R8A774B1 SoC support
   - fixes for H2 ES2.0

  sun4i:
   - vcc-dsi regulator support

  virtio-gpu:
   - vmexit vs spinlock fix
   - move to gem shmem helpers
   - handle large command buffers with cma"

* tag 'drm-next-2019-11-27' of git://anongit.freedesktop.org/drm/drm: (1855 commits)
  drm/amdgpu: invalidate mmhub semaphore workaround in gmc9/gmc10
  drm/amdgpu: initialize vm_inv_eng0_sem for gfxhub and mmhub
  drm/amd/amdgpu/sriov skip RLCG s/r list for arcturus VF.
  drm/amd/amdgpu/sriov temporarily skip ras,dtm,hdcp for arcturus VF
  drm/amdgpu/gfx10: re-init clear state buffer after gpu reset
  merge fix for "ftrace: Rework event_create_dir()"
  drm/amdgpu: Update Arcturus golden registers
  drm/amdgpu/gfx10: fix out-of-bound mqd_backup array access
  drm/amdgpu/gfx10: explicitly wait for cp idle after halt/unhalt
  Revert "drm/amd/display: enable S/G for RAVEN chip"
  drm/amdgpu: disable gfxoff on original raven
  drm/amdgpu: remove experimental flag for Navi14
  drm/amdgpu: disable gfxoff when using register read interface
  drm/amdgpu/powerplay: properly set PP_GFXOFF_MASK (v2)
  drm/amdgpu: fix bad DMA from INTERRUPT_CNTL2
  drm/radeon: fix bad DMA from INTERRUPT_CNTL2
  drm/amd/display: Fix debugfs on MST connectors
  drm/amdgpu/nv: add asic func for fetching vbios from rom directly
  drm/amdgpu: put flush_delayed_work at first
  drm/amdgpu/vcn2.5: fix the enc loop with hw fini
  ...
2019-11-27 17:45:48 -08:00

190 lines
4.3 KiB
C

/*
* SPDX-License-Identifier: MIT
*
* Copyright © 2014-2018 Intel Corporation
*/
#include "gem/i915_gem_object.h"
#include "i915_drv.h"
#include "intel_engine_pm.h"
#include "intel_engine_pool.h"
static struct intel_engine_cs *to_engine(struct intel_engine_pool *pool)
{
return container_of(pool, struct intel_engine_cs, pool);
}
static struct list_head *
bucket_for_size(struct intel_engine_pool *pool, size_t sz)
{
int n;
/*
* Compute a power-of-two bucket, but throw everything greater than
* 16KiB into the same bucket: i.e. the buckets hold objects of
* (1 page, 2 pages, 4 pages, 8+ pages).
*/
n = fls(sz >> PAGE_SHIFT) - 1;
if (n >= ARRAY_SIZE(pool->cache_list))
n = ARRAY_SIZE(pool->cache_list) - 1;
return &pool->cache_list[n];
}
static void node_free(struct intel_engine_pool_node *node)
{
i915_gem_object_put(node->obj);
i915_active_fini(&node->active);
kfree(node);
}
static int pool_active(struct i915_active *ref)
{
struct intel_engine_pool_node *node =
container_of(ref, typeof(*node), active);
struct dma_resv *resv = node->obj->base.resv;
int err;
if (dma_resv_trylock(resv)) {
dma_resv_add_excl_fence(resv, NULL);
dma_resv_unlock(resv);
}
err = i915_gem_object_pin_pages(node->obj);
if (err)
return err;
/* Hide this pinned object from the shrinker until retired */
i915_gem_object_make_unshrinkable(node->obj);
return 0;
}
__i915_active_call
static void pool_retire(struct i915_active *ref)
{
struct intel_engine_pool_node *node =
container_of(ref, typeof(*node), active);
struct intel_engine_pool *pool = node->pool;
struct list_head *list = bucket_for_size(pool, node->obj->base.size);
unsigned long flags;
GEM_BUG_ON(!intel_engine_pm_is_awake(to_engine(pool)));
i915_gem_object_unpin_pages(node->obj);
/* Return this object to the shrinker pool */
i915_gem_object_make_purgeable(node->obj);
spin_lock_irqsave(&pool->lock, flags);
list_add(&node->link, list);
spin_unlock_irqrestore(&pool->lock, flags);
}
static struct intel_engine_pool_node *
node_create(struct intel_engine_pool *pool, size_t sz)
{
struct intel_engine_cs *engine = to_engine(pool);
struct intel_engine_pool_node *node;
struct drm_i915_gem_object *obj;
node = kmalloc(sizeof(*node),
GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN);
if (!node)
return ERR_PTR(-ENOMEM);
node->pool = pool;
i915_active_init(&node->active, pool_active, pool_retire);
obj = i915_gem_object_create_internal(engine->i915, sz);
if (IS_ERR(obj)) {
i915_active_fini(&node->active);
kfree(node);
return ERR_CAST(obj);
}
i915_gem_object_set_readonly(obj);
node->obj = obj;
return node;
}
static struct intel_engine_pool *lookup_pool(struct intel_engine_cs *engine)
{
if (intel_engine_is_virtual(engine))
engine = intel_virtual_engine_get_sibling(engine, 0);
GEM_BUG_ON(!engine);
return &engine->pool;
}
struct intel_engine_pool_node *
intel_engine_get_pool(struct intel_engine_cs *engine, size_t size)
{
struct intel_engine_pool *pool = lookup_pool(engine);
struct intel_engine_pool_node *node;
struct list_head *list;
unsigned long flags;
int ret;
GEM_BUG_ON(!intel_engine_pm_is_awake(to_engine(pool)));
size = PAGE_ALIGN(size);
list = bucket_for_size(pool, size);
spin_lock_irqsave(&pool->lock, flags);
list_for_each_entry(node, list, link) {
if (node->obj->base.size < size)
continue;
list_del(&node->link);
break;
}
spin_unlock_irqrestore(&pool->lock, flags);
if (&node->link == list) {
node = node_create(pool, size);
if (IS_ERR(node))
return node;
}
ret = i915_active_acquire(&node->active);
if (ret) {
node_free(node);
return ERR_PTR(ret);
}
return node;
}
void intel_engine_pool_init(struct intel_engine_pool *pool)
{
int n;
spin_lock_init(&pool->lock);
for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++)
INIT_LIST_HEAD(&pool->cache_list[n]);
}
void intel_engine_pool_park(struct intel_engine_pool *pool)
{
int n;
for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) {
struct list_head *list = &pool->cache_list[n];
struct intel_engine_pool_node *node, *nn;
list_for_each_entry_safe(node, nn, list, link)
node_free(node);
INIT_LIST_HEAD(list);
}
}
void intel_engine_pool_fini(struct intel_engine_pool *pool)
{
int n;
for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++)
GEM_BUG_ON(!list_empty(&pool->cache_list[n]));
}