linux-stable/drivers/gpu/drm/i915/gt/intel_engine_user.c
Linus Torvalds 68a32ba141 drm for 5.13-rc1
- printk fourcc modifier support added %p4cc
 
 core:
 - drm_crtc_commit_wait
 - atomic plane state helpers reworked for full state
 - dma-buf heaps API rework
 - edid: rework and improvements for displayid
 
 dp-mst:
  - better topology logging
 
 bridge:
 - Chipone ICN6211
 - Lontium LT8912B
 - anx7625 regulator support
 
 panel:
 - fix lt9611 4k panels handling
 
 simple-kms:
 - add plane state helpers
 
 ttm:
 - debugfs support
 - removal of unused sysfs
 - ignore signaled moved fences
 - ioremap buffer according to mem caching
 
 i915:
 - Alderlake S enablement
 - Conversion to dma_resv_locking
 - Bring back watchdog timeout support
 - legacy ioctl cleanups
 - add GEM TDDO and RFC process
 - DG1 LMEM preparation work
 - intel_display.c refactoring
 - Gen9/TGL PCH combination support
 - eDP MSO Support
 - multiple PSR instance support
 - Link training debug updates
 - Disable PSR2 support on JSL/EHL
 - DDR5/LPDDR5 support for bw calcs
 - LSPCON limited to gen9/10 platforms
 - HSW/BDW async flip/VTd corruption workaround
 = SAGV watermakr fixes
 - SNB hard hang on ring resume fix
 - Limit imported dma-buf size
 - move to use new tasklet API
 - refactor KBL/TGL/ADL-S display/gt steppings
 - refactoring legacy DP/HDMI, FB plane code out
 
 amdgpu:
 - uapi: add ioctl to query video capabilities
 - Iniital AMD Freesync HDMI support
 - Initial Adebaran support
 - 10bpc dithering improvements
 - DCN secure display support
 - Drop legacy IO BAR requirements
 - PCIE/S0ix/RAS/Prime/Reset fixes
 - Display ASSR support
 - SMU gfx busy queues for RV/PCO
 - Initial LTTPR display work
 
 amdkfd:
 - MMU notifier fixes
 - APU fixes
 
 radeon:
 - debugfs cleanps
 - fw error handling ifix
 - Flexible array cleanups
 
 msm:
 - big DSI phy/pll cleanup
 - sc7280 initial support
 - commong bandwidth scaling path
 - shrinker locking contention fixes
 - unpin/swap support for GEM objcets
 
 ast:
 - cursor plane handling reworked
 
 tegra:
 - don't register DP AUX channels before connectors
 
 zynqmp:
 - fix OOB struct padding memset
 
 gma500:
 - drop ttm and medfield support
 
 exynos:
 - request_irq cleanup function
 
 mediatek:
 - fine tune line time for EOTp
 - MT8192 dpi support
 - atomic crtc config updates
 - don't support HDMI connector creation
 
 mxsdb:
 - imx8mm support
 
 panfrost:
 -= MMU IRQ handling rework
 
 qxl:
 - locking fixes
 - resource deallocation changes
 
 sun4i:
 - add alpha properties to UI/VI layers
 
 vc4:
 - RPi4 CEC support
 
 vmwgfx:
 - doc cleanups
 
 arc:
 - moved to drm/tiny
 -----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJgiNSVAAoJEAx081l5xIa+fvYP/1206BfOYOx5opt5K3By06ZY
 zrOsbeaqFdHzfUR7xVwO4vqQNhkX4Pt8H/U7uYZx8PRdrXzGENwWLIaIskyUrKOd
 BtwNqUr0ZXJGDlGg26StnUHKeAXuYXlpBKLta5y4LUTkI+bm6V/oVaDMq4dnah70
 2CXS4C2mnaFRLBzuRlraxoGFN4eZkz6Waeyo6PJxn/l2GE2gw+jho0Yrh8e8F2w5
 EjQeNF22/uHwznov03XFJlyugecuBDbE8A6Ma/znnkVdBXcT94eUMugbKOKi4Nn6
 PuJOEdJxmj/9s3oi6kBERc8dvpOj0O+8Vp+xOzn2U3BVXebvu7VoJsq6FcAvL5lN
 ltj4iErxUlEud2GRIVUMx8OTFiKj4ThRFJ2/8Uf22r3P7RHO5E9BLnZBzqIAhDVr
 s2cDBMItcxcVHRCmE04h12XAO4libZBb2TVjbqG94Acq7beR76pMszFrmxPmHBEm
 NGe1s7+ajxMzsq/NIsk4XAhqSmJo6+ujKyyVnrgvKUVeEaWW1U4YvjhJaetnP4fB
 47gF24wOSNFwiCUZlqaIpp/MR4Z8YmaJ7tayWQq4Oj/neWe/yc8xQgQIuE8GL20j
 P9eNQNvlBnoxkz275M9x4kVhJ5FRjr7OYnd3sFVnALuj6fnL3Z1RXLqI1lNtIz1d
 YM89veZuNxMaiDz8roPH
 =bLWZ
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2021-04-28' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "The usual lots of work all over the place.

  i915 has gotten some Alderlake work and prelim DG1 code, along with a
  major locking rework over the GEM code, and brings back the property
  of timing out long running jobs using a watchdog. amdgpu has some
  Alderbran support (new GPU), freesync HDMI support along with a lot
  other fixes.

  Outside of the drm, there is a new printf specifier added which should
  have all the correct acks/sobs:

   - printk fourcc modifier support added %p4cc

  Summary:

  core:
   - drm_crtc_commit_wait
   - atomic plane state helpers reworked for full state
   - dma-buf heaps API rework
   - edid: rework and improvements for displayid

  dp-mst:
   - better topology logging

  bridge:
   - Chipone ICN6211
   - Lontium LT8912B
   - anx7625 regulator support

  panel:
   - fix lt9611 4k panels handling

  simple-kms:
   - add plane state helpers

  ttm:
   - debugfs support
   - removal of unused sysfs
   - ignore signaled moved fences
   - ioremap buffer according to mem caching

  i915:
   - Alderlake S enablement
   - Conversion to dma_resv_locking
   - Bring back watchdog timeout support
   - legacy ioctl cleanups
   - add GEM TDDO and RFC process
   - DG1 LMEM preparation work
   - intel_display.c refactoring
   - Gen9/TGL PCH combination support
   - eDP MSO Support
   - multiple PSR instance support
   - Link training debug updates
   - Disable PSR2 support on JSL/EHL
   - DDR5/LPDDR5 support for bw calcs
   - LSPCON limited to gen9/10 platforms
   - HSW/BDW async flip/VTd corruption workaround
   - SAGV watermark fixes
   - SNB hard hang on ring resume fix
   - Limit imported dma-buf size
   - move to use new tasklet API
   - refactor KBL/TGL/ADL-S display/gt steppings
   - refactoring legacy DP/HDMI, FB plane code out

  amdgpu:
   - uapi: add ioctl to query video capabilities
   - Iniital AMD Freesync HDMI support
   - Initial Adebaran support
   - 10bpc dithering improvements
   - DCN secure display support
   - Drop legacy IO BAR requirements
   - PCIE/S0ix/RAS/Prime/Reset fixes
   - Display ASSR support
   - SMU gfx busy queues for RV/PCO
   - Initial LTTPR display work

  amdkfd:
   - MMU notifier fixes
   - APU fixes

  radeon:
   - debugfs cleanps
   - fw error handling ifix
   - Flexible array cleanups

  msm:
   - big DSI phy/pll cleanup
   - sc7280 initial support
   - commong bandwidth scaling path
   - shrinker locking contention fixes
   - unpin/swap support for GEM objcets

  ast:
   - cursor plane handling reworked

  tegra:
   - don't register DP AUX channels before connectors

  zynqmp:
   - fix OOB struct padding memset

  gma500:
   - drop ttm and medfield support

  exynos:
   - request_irq cleanup function

  mediatek:
   - fine tune line time for EOTp
   - MT8192 dpi support
   - atomic crtc config updates
   - don't support HDMI connector creation

  mxsdb:
   - imx8mm support

  panfrost:
   - MMU IRQ handling rework

  qxl:
   - locking fixes
   - resource deallocation changes

  sun4i:
   - add alpha properties to UI/VI layers

  vc4:
   - RPi4 CEC support

  vmwgfx:
   - doc cleanups

  arc:
   - moved to drm/tiny"

* tag 'drm-next-2021-04-28' of git://anongit.freedesktop.org/drm/drm: (1390 commits)
  drm/ttm: Don't count pages in SG BOs against pages_limit
  drm/ttm: fix return value check
  drm/bridge: lt8912b: fix incorrect handling of of_* return values
  drm: bridge: fix LONTIUM use of mipi_dsi_() functions
  drm: bridge: fix ANX7625 use of mipi_dsi_() functions
  drm/amdgpu: page retire over debugfs mechanism
  drm/radeon: Fix a missing check bug in radeon_dp_mst_detect()
  drm/amd/display: Fix the Wunused-function warning
  drm/radeon/r600: Fix variables that are not used after assignment
  drm/amdgpu/smu7: fix CAC setting on TOPAZ
  drm/amd/display: Update DCN302 SR Exit Latency
  drm/amdgpu: enable ras eeprom on aldebaran
  drm/amdgpu: RAS harvest on driver load
  drm/amdgpu: add ras aldebaran ras eeprom driver
  drm/amd/pm: increase time out value when sending msg to SMU
  drm/amdgpu: add DMUB outbox event IRQ source define/complete/debug flag
  drm/amd/pm: add the callback to get vbios bootup values for vangogh
  drm/radeon: Fix size overflow
  drm/amdgpu: Fix size overflow
  drm/amdgpu: move mmhub ras_func init to ip specific file
  ...
2021-04-28 10:01:40 -07:00

300 lines
7.6 KiB
C

// SPDX-License-Identifier: MIT
/*
* Copyright © 2019 Intel Corporation
*/
#include <linux/list.h>
#include <linux/list_sort.h>
#include <linux/llist.h>
#include "i915_drv.h"
#include "intel_engine.h"
#include "intel_engine_user.h"
#include "intel_gt.h"
struct intel_engine_cs *
intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance)
{
struct rb_node *p = i915->uabi_engines.rb_node;
while (p) {
struct intel_engine_cs *it =
rb_entry(p, typeof(*it), uabi_node);
if (class < it->uabi_class)
p = p->rb_left;
else if (class > it->uabi_class ||
instance > it->uabi_instance)
p = p->rb_right;
else if (instance < it->uabi_instance)
p = p->rb_left;
else
return it;
}
return NULL;
}
void intel_engine_add_user(struct intel_engine_cs *engine)
{
llist_add((struct llist_node *)&engine->uabi_node,
(struct llist_head *)&engine->i915->uabi_engines);
}
static const u8 uabi_classes[] = {
[RENDER_CLASS] = I915_ENGINE_CLASS_RENDER,
[COPY_ENGINE_CLASS] = I915_ENGINE_CLASS_COPY,
[VIDEO_DECODE_CLASS] = I915_ENGINE_CLASS_VIDEO,
[VIDEO_ENHANCEMENT_CLASS] = I915_ENGINE_CLASS_VIDEO_ENHANCE,
};
static int engine_cmp(void *priv, const struct list_head *A,
const struct list_head *B)
{
const struct intel_engine_cs *a =
container_of((struct rb_node *)A, typeof(*a), uabi_node);
const struct intel_engine_cs *b =
container_of((struct rb_node *)B, typeof(*b), uabi_node);
if (uabi_classes[a->class] < uabi_classes[b->class])
return -1;
if (uabi_classes[a->class] > uabi_classes[b->class])
return 1;
if (a->instance < b->instance)
return -1;
if (a->instance > b->instance)
return 1;
return 0;
}
static struct llist_node *get_engines(struct drm_i915_private *i915)
{
return llist_del_all((struct llist_head *)&i915->uabi_engines);
}
static void sort_engines(struct drm_i915_private *i915,
struct list_head *engines)
{
struct llist_node *pos, *next;
llist_for_each_safe(pos, next, get_engines(i915)) {
struct intel_engine_cs *engine =
container_of((struct rb_node *)pos, typeof(*engine),
uabi_node);
list_add((struct list_head *)&engine->uabi_node, engines);
}
list_sort(NULL, engines, engine_cmp);
}
static void set_scheduler_caps(struct drm_i915_private *i915)
{
static const struct {
u8 engine;
u8 sched;
} map[] = {
#define MAP(x, y) { ilog2(I915_ENGINE_##x), ilog2(I915_SCHEDULER_CAP_##y) }
MAP(HAS_PREEMPTION, PREEMPTION),
MAP(HAS_SEMAPHORES, SEMAPHORES),
MAP(SUPPORTS_STATS, ENGINE_BUSY_STATS),
#undef MAP
};
struct intel_engine_cs *engine;
u32 enabled, disabled;
enabled = 0;
disabled = 0;
for_each_uabi_engine(engine, i915) { /* all engines must agree! */
int i;
if (engine->schedule)
enabled |= (I915_SCHEDULER_CAP_ENABLED |
I915_SCHEDULER_CAP_PRIORITY);
else
disabled |= (I915_SCHEDULER_CAP_ENABLED |
I915_SCHEDULER_CAP_PRIORITY);
for (i = 0; i < ARRAY_SIZE(map); i++) {
if (engine->flags & BIT(map[i].engine))
enabled |= BIT(map[i].sched);
else
disabled |= BIT(map[i].sched);
}
}
i915->caps.scheduler = enabled & ~disabled;
if (!(i915->caps.scheduler & I915_SCHEDULER_CAP_ENABLED))
i915->caps.scheduler = 0;
}
const char *intel_engine_class_repr(u8 class)
{
static const char * const uabi_names[] = {
[RENDER_CLASS] = "rcs",
[COPY_ENGINE_CLASS] = "bcs",
[VIDEO_DECODE_CLASS] = "vcs",
[VIDEO_ENHANCEMENT_CLASS] = "vecs",
};
if (class >= ARRAY_SIZE(uabi_names) || !uabi_names[class])
return "xxx";
return uabi_names[class];
}
struct legacy_ring {
struct intel_gt *gt;
u8 class;
u8 instance;
};
static int legacy_ring_idx(const struct legacy_ring *ring)
{
static const struct {
u8 base, max;
} map[] = {
[RENDER_CLASS] = { RCS0, 1 },
[COPY_ENGINE_CLASS] = { BCS0, 1 },
[VIDEO_DECODE_CLASS] = { VCS0, I915_MAX_VCS },
[VIDEO_ENHANCEMENT_CLASS] = { VECS0, I915_MAX_VECS },
};
if (GEM_DEBUG_WARN_ON(ring->class >= ARRAY_SIZE(map)))
return INVALID_ENGINE;
if (GEM_DEBUG_WARN_ON(ring->instance >= map[ring->class].max))
return INVALID_ENGINE;
return map[ring->class].base + ring->instance;
}
static void add_legacy_ring(struct legacy_ring *ring,
struct intel_engine_cs *engine)
{
if (engine->gt != ring->gt || engine->class != ring->class) {
ring->gt = engine->gt;
ring->class = engine->class;
ring->instance = 0;
}
engine->legacy_idx = legacy_ring_idx(ring);
if (engine->legacy_idx != INVALID_ENGINE)
ring->instance++;
}
void intel_engines_driver_register(struct drm_i915_private *i915)
{
struct legacy_ring ring = {};
u8 uabi_instances[4] = {};
struct list_head *it, *next;
struct rb_node **p, *prev;
LIST_HEAD(engines);
sort_engines(i915, &engines);
prev = NULL;
p = &i915->uabi_engines.rb_node;
list_for_each_safe(it, next, &engines) {
struct intel_engine_cs *engine =
container_of((struct rb_node *)it, typeof(*engine),
uabi_node);
char old[sizeof(engine->name)];
if (intel_gt_has_unrecoverable_error(engine->gt))
continue; /* ignore incomplete engines */
GEM_BUG_ON(engine->class >= ARRAY_SIZE(uabi_classes));
engine->uabi_class = uabi_classes[engine->class];
GEM_BUG_ON(engine->uabi_class >= ARRAY_SIZE(uabi_instances));
engine->uabi_instance = uabi_instances[engine->uabi_class]++;
/* Replace the internal name with the final user facing name */
memcpy(old, engine->name, sizeof(engine->name));
scnprintf(engine->name, sizeof(engine->name), "%s%u",
intel_engine_class_repr(engine->class),
engine->uabi_instance);
DRM_DEBUG_DRIVER("renamed %s to %s\n", old, engine->name);
rb_link_node(&engine->uabi_node, prev, p);
rb_insert_color(&engine->uabi_node, &i915->uabi_engines);
GEM_BUG_ON(intel_engine_lookup_user(i915,
engine->uabi_class,
engine->uabi_instance) != engine);
/* Fix up the mapping to match default execbuf::user_map[] */
add_legacy_ring(&ring, engine);
prev = &engine->uabi_node;
p = &prev->rb_right;
}
if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) &&
IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) {
struct intel_engine_cs *engine;
unsigned int isolation;
int class, inst;
int errors = 0;
for (class = 0; class < ARRAY_SIZE(uabi_instances); class++) {
for (inst = 0; inst < uabi_instances[class]; inst++) {
engine = intel_engine_lookup_user(i915,
class, inst);
if (!engine) {
pr_err("UABI engine not found for { class:%d, instance:%d }\n",
class, inst);
errors++;
continue;
}
if (engine->uabi_class != class ||
engine->uabi_instance != inst) {
pr_err("Wrong UABI engine:%s { class:%d, instance:%d } found for { class:%d, instance:%d }\n",
engine->name,
engine->uabi_class,
engine->uabi_instance,
class, inst);
errors++;
continue;
}
}
}
/*
* Make sure that classes with multiple engine instances all
* share the same basic configuration.
*/
isolation = intel_engines_has_context_isolation(i915);
for_each_uabi_engine(engine, i915) {
unsigned int bit = BIT(engine->uabi_class);
unsigned int expected = engine->default_state ? bit : 0;
if ((isolation & bit) != expected) {
pr_err("mismatching default context state for class %d on engine %s\n",
engine->uabi_class, engine->name);
errors++;
}
}
if (drm_WARN(&i915->drm, errors,
"Invalid UABI engine mapping found"))
i915->uabi_engines = RB_ROOT;
}
set_scheduler_caps(i915);
}
unsigned int intel_engines_has_context_isolation(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
unsigned int which;
which = 0;
for_each_uabi_engine(engine, i915)
if (engine->default_state)
which |= BIT(engine->uabi_class);
return which;
}