2018-04-30 11:10:58 -07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
|
|
|
/* Copyright (C) 2014-2018 Broadcom */
|
|
|
|
|
2019-07-16 08:42:03 +02:00
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <linux/io.h>
|
2018-04-30 11:10:58 -07:00
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/pm_runtime.h>
|
2019-03-08 09:43:36 -08:00
|
|
|
#include <linux/reset.h>
|
2018-04-30 11:10:58 -07:00
|
|
|
#include <linux/sched/signal.h>
|
2019-07-16 08:42:03 +02:00
|
|
|
#include <linux/uaccess.h>
|
|
|
|
|
|
|
|
#include <drm/drm_syncobj.h>
|
|
|
|
#include <uapi/drm/v3d_drm.h>
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
#include "v3d_drv.h"
|
|
|
|
#include "v3d_regs.h"
|
|
|
|
#include "v3d_trace.h"
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_init_core(struct v3d_dev *v3d, int core)
|
|
|
|
{
|
|
|
|
/* Set OVRTMUOUT, which means that the texture sampler uniform
|
|
|
|
* configuration's tmu output type field is used, instead of
|
|
|
|
* using the hardware default behavior based on the texture
|
|
|
|
* type. If you want the default behavior, you can still put
|
|
|
|
* "2" in the indirect texture state's output_type field.
|
|
|
|
*/
|
2019-02-20 15:36:57 -08:00
|
|
|
if (v3d->ver < 40)
|
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_MISCCFG, V3D_MISCCFG_OVRTMUOUT);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
/* Whenever we flush the L2T cache, we always want to flush
|
|
|
|
* the whole thing.
|
|
|
|
*/
|
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_L2TFLSTA, 0);
|
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_L2TFLEND, ~0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sets invariant state for the HW. */
|
|
|
|
static void
|
|
|
|
v3d_init_hw_state(struct v3d_dev *v3d)
|
|
|
|
{
|
|
|
|
v3d_init_core(v3d, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_idle_axi(struct v3d_dev *v3d, int core)
|
|
|
|
{
|
|
|
|
V3D_CORE_WRITE(core, V3D_GMP_CFG, V3D_GMP_CFG_STOP_REQ);
|
|
|
|
|
|
|
|
if (wait_for((V3D_CORE_READ(core, V3D_GMP_STATUS) &
|
|
|
|
(V3D_GMP_STATUS_RD_COUNT_MASK |
|
|
|
|
V3D_GMP_STATUS_WR_COUNT_MASK |
|
|
|
|
V3D_GMP_STATUS_CFG_BUSY)) == 0, 100)) {
|
|
|
|
DRM_ERROR("Failed to wait for safe GMP shutdown\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_idle_gca(struct v3d_dev *v3d)
|
|
|
|
{
|
|
|
|
if (v3d->ver >= 41)
|
|
|
|
return;
|
|
|
|
|
|
|
|
V3D_GCA_WRITE(V3D_GCA_SAFE_SHUTDOWN, V3D_GCA_SAFE_SHUTDOWN_EN);
|
|
|
|
|
|
|
|
if (wait_for((V3D_GCA_READ(V3D_GCA_SAFE_SHUTDOWN_ACK) &
|
|
|
|
V3D_GCA_SAFE_SHUTDOWN_ACK_ACKED) ==
|
|
|
|
V3D_GCA_SAFE_SHUTDOWN_ACK_ACKED, 100)) {
|
|
|
|
DRM_ERROR("Failed to wait for safe GCA shutdown\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-03-08 09:43:36 -08:00
|
|
|
v3d_reset_by_bridge(struct v3d_dev *v3d)
|
2018-04-30 11:10:58 -07:00
|
|
|
{
|
|
|
|
int version = V3D_BRIDGE_READ(V3D_TOP_GR_BRIDGE_REVISION);
|
|
|
|
|
|
|
|
if (V3D_GET_FIELD(version, V3D_TOP_GR_BRIDGE_MAJOR) == 2) {
|
|
|
|
V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_0,
|
|
|
|
V3D_TOP_GR_BRIDGE_SW_INIT_0_V3D_CLK_108_SW_INIT);
|
|
|
|
V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_0, 0);
|
|
|
|
|
|
|
|
/* GFXH-1383: The SW_INIT may cause a stray write to address 0
|
|
|
|
* of the unit, so reset it to its power-on value here.
|
|
|
|
*/
|
|
|
|
V3D_WRITE(V3D_HUB_AXICFG, V3D_HUB_AXICFG_MAX_LEN_MASK);
|
|
|
|
} else {
|
|
|
|
WARN_ON_ONCE(V3D_GET_FIELD(version,
|
|
|
|
V3D_TOP_GR_BRIDGE_MAJOR) != 7);
|
|
|
|
V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1,
|
|
|
|
V3D_TOP_GR_BRIDGE_SW_INIT_1_V3D_CLK_108_SW_INIT);
|
|
|
|
V3D_BRIDGE_WRITE(V3D_TOP_GR_BRIDGE_SW_INIT_1, 0);
|
|
|
|
}
|
2019-03-08 09:43:36 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_reset_v3d(struct v3d_dev *v3d)
|
|
|
|
{
|
|
|
|
if (v3d->reset)
|
|
|
|
reset_control_reset(v3d->reset);
|
|
|
|
else
|
|
|
|
v3d_reset_by_bridge(v3d);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
v3d_init_hw_state(v3d);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3d_reset(struct v3d_dev *v3d)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = &v3d->drm;
|
|
|
|
|
2019-04-18 17:10:13 -07:00
|
|
|
DRM_DEV_ERROR(dev->dev, "Resetting GPU for hang.\n");
|
|
|
|
DRM_DEV_ERROR(dev->dev, "V3D_ERR_STAT: 0x%08x\n",
|
|
|
|
V3D_CORE_READ(0, V3D_ERR_STAT));
|
2018-04-30 11:10:58 -07:00
|
|
|
trace_v3d_reset_begin(dev);
|
|
|
|
|
|
|
|
/* XXX: only needed for safe powerdown, not reset. */
|
|
|
|
if (false)
|
|
|
|
v3d_idle_axi(v3d, 0);
|
|
|
|
|
|
|
|
v3d_idle_gca(v3d);
|
|
|
|
v3d_reset_v3d(v3d);
|
|
|
|
|
|
|
|
v3d_mmu_set_page_table(v3d);
|
|
|
|
v3d_irq_reset(v3d);
|
|
|
|
|
2021-06-08 13:15:41 +02:00
|
|
|
v3d_perfmon_stop(v3d, v3d->active_perfmon, false);
|
|
|
|
|
2018-04-30 11:10:58 -07:00
|
|
|
trace_v3d_reset_end(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_flush_l3(struct v3d_dev *v3d)
|
|
|
|
{
|
|
|
|
if (v3d->ver < 41) {
|
|
|
|
u32 gca_ctrl = V3D_GCA_READ(V3D_GCA_CACHE_CTRL);
|
|
|
|
|
|
|
|
V3D_GCA_WRITE(V3D_GCA_CACHE_CTRL,
|
|
|
|
gca_ctrl | V3D_GCA_CACHE_CTRL_FLUSH);
|
|
|
|
|
|
|
|
if (v3d->ver < 33) {
|
|
|
|
V3D_GCA_WRITE(V3D_GCA_CACHE_CTRL,
|
|
|
|
gca_ctrl & ~V3D_GCA_CACHE_CTRL_FLUSH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-03 14:24:37 -08:00
|
|
|
/* Invalidates the (read-only) L2C cache. This was the L2 cache for
|
|
|
|
* uniforms and instructions on V3D 3.2.
|
|
|
|
*/
|
2018-04-30 11:10:58 -07:00
|
|
|
static void
|
2018-12-03 14:24:37 -08:00
|
|
|
v3d_invalidate_l2c(struct v3d_dev *v3d, int core)
|
2018-04-30 11:10:58 -07:00
|
|
|
{
|
2018-12-03 14:24:37 -08:00
|
|
|
if (v3d->ver > 32)
|
|
|
|
return;
|
|
|
|
|
2018-04-30 11:10:58 -07:00
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_L2CACTL,
|
|
|
|
V3D_L2CACTL_L2CCLR |
|
|
|
|
V3D_L2CACTL_L2CENA);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalidates texture L2 cachelines */
|
|
|
|
static void
|
|
|
|
v3d_flush_l2t(struct v3d_dev *v3d, int core)
|
|
|
|
{
|
2018-12-03 14:24:36 -08:00
|
|
|
/* While there is a busy bit (V3D_L2TCACTL_L2TFLS), we don't
|
|
|
|
* need to wait for completion before dispatching the job --
|
|
|
|
* L2T accesses will be stalled until the flush has completed.
|
2019-04-16 15:58:54 -07:00
|
|
|
* However, we do need to make sure we don't try to trigger a
|
|
|
|
* new flush while the L2_CLEAN queue is trying to
|
|
|
|
* synchronously clean after a job.
|
2018-12-03 14:24:36 -08:00
|
|
|
*/
|
2019-04-16 15:58:54 -07:00
|
|
|
mutex_lock(&v3d->cache_clean_lock);
|
2018-04-30 11:10:58 -07:00
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
|
|
|
|
V3D_L2TCACTL_L2TFLS |
|
|
|
|
V3D_SET_FIELD(V3D_L2TCACTL_FLM_FLUSH, V3D_L2TCACTL_FLM));
|
2019-04-16 15:58:54 -07:00
|
|
|
mutex_unlock(&v3d->cache_clean_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Cleans texture L1 and L2 cachelines (writing back dirty data).
|
|
|
|
*
|
|
|
|
* For cleaning, which happens from the CACHE_CLEAN queue after CSD has
|
|
|
|
* executed, we need to make sure that the clean is done before
|
|
|
|
* signaling job completion. So, we synchronously wait before
|
|
|
|
* returning, and we make sure that L2 invalidates don't happen in the
|
|
|
|
* meantime to confuse our are-we-done checks.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
v3d_clean_caches(struct v3d_dev *v3d)
|
|
|
|
{
|
|
|
|
struct drm_device *dev = &v3d->drm;
|
|
|
|
int core = 0;
|
|
|
|
|
|
|
|
trace_v3d_cache_clean_begin(dev);
|
|
|
|
|
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
|
|
|
|
if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
|
2021-09-15 12:05:07 +02:00
|
|
|
V3D_L2TCACTL_TMUWCF), 100)) {
|
|
|
|
DRM_ERROR("Timeout waiting for TMU write combiner flush\n");
|
2019-04-16 15:58:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
mutex_lock(&v3d->cache_clean_lock);
|
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL,
|
|
|
|
V3D_L2TCACTL_L2TFLS |
|
|
|
|
V3D_SET_FIELD(V3D_L2TCACTL_FLM_CLEAN, V3D_L2TCACTL_FLM));
|
|
|
|
|
|
|
|
if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
|
|
|
|
V3D_L2TCACTL_L2TFLS), 100)) {
|
|
|
|
DRM_ERROR("Timeout waiting for L2T clean\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
mutex_unlock(&v3d->cache_clean_lock);
|
|
|
|
|
|
|
|
trace_v3d_cache_clean_end(dev);
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Invalidates the slice caches. These are read-only caches. */
|
|
|
|
static void
|
|
|
|
v3d_invalidate_slices(struct v3d_dev *v3d, int core)
|
|
|
|
{
|
|
|
|
V3D_CORE_WRITE(core, V3D_CTL_SLCACTL,
|
|
|
|
V3D_SET_FIELD(0xf, V3D_SLCACTL_TVCCS) |
|
|
|
|
V3D_SET_FIELD(0xf, V3D_SLCACTL_TDCCS) |
|
|
|
|
V3D_SET_FIELD(0xf, V3D_SLCACTL_UCC) |
|
|
|
|
V3D_SET_FIELD(0xf, V3D_SLCACTL_ICC));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3d_invalidate_caches(struct v3d_dev *v3d)
|
|
|
|
{
|
2018-12-03 14:24:38 -08:00
|
|
|
/* Invalidate the caches from the outside in. That way if
|
|
|
|
* another CL's concurrent use of nearby memory were to pull
|
|
|
|
* an invalidated cacheline back in, we wouldn't leave stale
|
|
|
|
* data in the inner cache.
|
|
|
|
*/
|
2018-04-30 11:10:58 -07:00
|
|
|
v3d_flush_l3(v3d);
|
2018-12-03 14:24:37 -08:00
|
|
|
v3d_invalidate_l2c(v3d, 0);
|
2018-04-30 11:10:58 -07:00
|
|
|
v3d_flush_l2t(v3d, 0);
|
2018-12-03 14:24:38 -08:00
|
|
|
v3d_invalidate_slices(v3d, 0);
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Takes the reservation lock on all the BOs being referenced, so that
|
|
|
|
* at queue submit time we can update the reservations.
|
|
|
|
*
|
|
|
|
* We don't lock the RCL the tile alloc/state BOs, or overflow memory
|
|
|
|
* (all of which are on exec->unref_list). They're entirely private
|
|
|
|
* to v3d, so we don't attach dma-buf fences to them.
|
|
|
|
*/
|
|
|
|
static int
|
2019-04-16 15:58:56 -07:00
|
|
|
v3d_lock_bo_reservations(struct v3d_job *job,
|
2018-04-30 11:10:58 -07:00
|
|
|
struct ww_acquire_ctx *acquire_ctx)
|
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
|
2019-04-16 15:58:56 -07:00
|
|
|
ret = drm_gem_lock_reservations(job->bo, job->bo_count, acquire_ctx);
|
2019-03-08 08:17:14 -08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:56 -07:00
|
|
|
for (i = 0; i < job->bo_count; i++) {
|
2021-08-05 12:46:55 +02:00
|
|
|
ret = drm_sched_job_add_implicit_dependencies(&job->base,
|
|
|
|
job->bo[i], true);
|
2019-04-16 15:58:56 -07:00
|
|
|
if (ret) {
|
|
|
|
drm_gem_unlock_reservations(job->bo, job->bo_count,
|
|
|
|
acquire_ctx);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-30 11:10:58 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-04-16 15:58:53 -07:00
|
|
|
* v3d_lookup_bos() - Sets up job->bo[] with the GEM objects
|
2018-04-30 11:10:58 -07:00
|
|
|
* referenced by the job.
|
|
|
|
* @dev: DRM device
|
|
|
|
* @file_priv: DRM file for this fd
|
2019-04-16 15:58:53 -07:00
|
|
|
* @job: V3D job being set up
|
2020-11-16 17:41:05 +00:00
|
|
|
* @bo_handles: GEM handles
|
|
|
|
* @bo_count: Number of GEM handles passed in
|
2018-04-30 11:10:58 -07:00
|
|
|
*
|
|
|
|
* The command validator needs to reference BOs by their index within
|
|
|
|
* the submitted job's BO list. This does the validation of the job's
|
|
|
|
* BO list and reference counting for the lifetime of the job.
|
|
|
|
*
|
|
|
|
* Note that this function doesn't need to unreference the BOs on
|
|
|
|
* failure, because that will happen at v3d_exec_cleanup() time.
|
|
|
|
*/
|
|
|
|
static int
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_lookup_bos(struct drm_device *dev,
|
|
|
|
struct drm_file *file_priv,
|
|
|
|
struct v3d_job *job,
|
|
|
|
u64 bo_handles,
|
|
|
|
u32 bo_count)
|
2018-04-30 11:10:58 -07:00
|
|
|
{
|
|
|
|
u32 *handles;
|
|
|
|
int ret = 0;
|
|
|
|
int i;
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
job->bo_count = bo_count;
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
if (!job->bo_count) {
|
2018-04-30 11:10:58 -07:00
|
|
|
/* See comment on bo_index for why we have to check
|
|
|
|
* this.
|
|
|
|
*/
|
|
|
|
DRM_DEBUG("Rendering requires BOs\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
job->bo = kvmalloc_array(job->bo_count,
|
|
|
|
sizeof(struct drm_gem_cma_object *),
|
|
|
|
GFP_KERNEL | __GFP_ZERO);
|
|
|
|
if (!job->bo) {
|
2018-04-30 11:10:58 -07:00
|
|
|
DRM_DEBUG("Failed to allocate validated BO pointers\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
handles = kvmalloc_array(job->bo_count, sizeof(u32), GFP_KERNEL);
|
2018-04-30 11:10:58 -07:00
|
|
|
if (!handles) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
DRM_DEBUG("Failed to allocate incoming GEM handles\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (copy_from_user(handles,
|
2019-04-16 15:58:53 -07:00
|
|
|
(void __user *)(uintptr_t)bo_handles,
|
|
|
|
job->bo_count * sizeof(u32))) {
|
2018-04-30 11:10:58 -07:00
|
|
|
ret = -EFAULT;
|
|
|
|
DRM_DEBUG("Failed to copy in GEM handles\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock(&file_priv->table_lock);
|
2019-04-16 15:58:53 -07:00
|
|
|
for (i = 0; i < job->bo_count; i++) {
|
2018-04-30 11:10:58 -07:00
|
|
|
struct drm_gem_object *bo = idr_find(&file_priv->object_idr,
|
|
|
|
handles[i]);
|
|
|
|
if (!bo) {
|
|
|
|
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
|
|
|
|
i, handles[i]);
|
|
|
|
ret = -ENOENT;
|
|
|
|
spin_unlock(&file_priv->table_lock);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
drm_gem_object_get(bo);
|
2019-04-16 15:58:53 -07:00
|
|
|
job->bo[i] = bo;
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|
|
|
|
spin_unlock(&file_priv->table_lock);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
kvfree(handles);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_job_free(struct kref *ref)
|
2018-04-30 11:10:58 -07:00
|
|
|
{
|
2019-04-16 15:58:53 -07:00
|
|
|
struct v3d_job *job = container_of(ref, struct v3d_job, refcount);
|
|
|
|
int i;
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
for (i = 0; i < job->bo_count; i++) {
|
|
|
|
if (job->bo[i])
|
2020-05-15 10:51:12 +01:00
|
|
|
drm_gem_object_put(job->bo[i]);
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|
2019-04-16 15:58:53 -07:00
|
|
|
kvfree(job->bo);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
dma_fence_put(job->irq_fence);
|
|
|
|
dma_fence_put(job->done_fence);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2020-04-15 09:39:44 +02:00
|
|
|
pm_runtime_mark_last_busy(job->v3d->drm.dev);
|
|
|
|
pm_runtime_put_autosuspend(job->v3d->drm.dev);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2021-06-08 13:15:41 +02:00
|
|
|
if (job->perfmon)
|
|
|
|
v3d_perfmon_put(job->perfmon);
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
kfree(job);
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|
|
|
|
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
static void
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_render_job_free(struct kref *ref)
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
{
|
2019-04-16 15:58:53 -07:00
|
|
|
struct v3d_render_job *job = container_of(ref, struct v3d_render_job,
|
|
|
|
base.refcount);
|
|
|
|
struct v3d_bo *bo, *save;
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) {
|
2020-05-15 10:51:12 +01:00
|
|
|
drm_gem_object_put(&bo->base.base);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_job_free(ref);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
}
|
|
|
|
|
2021-08-05 12:46:54 +02:00
|
|
|
void v3d_job_cleanup(struct v3d_job *job)
|
|
|
|
{
|
2021-09-30 17:17:39 +01:00
|
|
|
if (!job)
|
|
|
|
return;
|
|
|
|
|
2021-08-05 12:46:54 +02:00
|
|
|
drm_sched_job_cleanup(&job->base);
|
|
|
|
v3d_job_put(job);
|
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
void v3d_job_put(struct v3d_job *job)
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
{
|
2019-04-16 15:58:53 -07:00
|
|
|
kref_put(&job->refcount, job->free);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
}
|
|
|
|
|
2018-04-30 11:10:58 -07:00
|
|
|
int
|
|
|
|
v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct drm_v3d_wait_bo *args = data;
|
|
|
|
ktime_t start = ktime_get();
|
|
|
|
u64 delta_ns;
|
|
|
|
unsigned long timeout_jiffies =
|
|
|
|
nsecs_to_jiffies_timeout(args->timeout_ns);
|
|
|
|
|
|
|
|
if (args->pad != 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2019-08-11 10:06:32 +02:00
|
|
|
ret = drm_gem_dma_resv_wait(file_priv, args->handle,
|
2021-09-30 17:15:22 +01:00
|
|
|
true, timeout_jiffies);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
/* Decrement the user's timeout, in case we got interrupted
|
|
|
|
* such that the ioctl will be restarted.
|
|
|
|
*/
|
|
|
|
delta_ns = ktime_to_ns(ktime_sub(ktime_get(), start));
|
|
|
|
if (delta_ns < args->timeout_ns)
|
|
|
|
args->timeout_ns -= delta_ns;
|
|
|
|
else
|
|
|
|
args->timeout_ns = 0;
|
|
|
|
|
|
|
|
/* Asked to wait beyond the jiffie/scheduler precision? */
|
|
|
|
if (ret == -ETIME && args->timeout_ns)
|
|
|
|
ret = -EAGAIN;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:15:22 +01:00
|
|
|
static int
|
|
|
|
v3d_job_add_deps(struct drm_file *file_priv, struct v3d_job *job,
|
|
|
|
u32 in_sync, u32 point)
|
|
|
|
{
|
|
|
|
struct dma_fence *in_fence = NULL;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = drm_syncobj_find_fence(file_priv, in_sync, point, 0, &in_fence);
|
|
|
|
if (ret == -EINVAL)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
return drm_sched_job_add_dependency(&job->base, in_fence);
|
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
static int
|
|
|
|
v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv,
|
2021-09-30 17:17:39 +01:00
|
|
|
void **container, size_t size, void (*free)(struct kref *ref),
|
2021-09-30 17:19:56 +01:00
|
|
|
u32 in_sync, struct v3d_submit_ext *se, enum v3d_queue queue)
|
2019-04-16 15:58:53 -07:00
|
|
|
{
|
2021-08-05 12:46:54 +02:00
|
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
2021-09-30 17:17:39 +01:00
|
|
|
struct v3d_job *job;
|
2021-09-30 17:19:56 +01:00
|
|
|
bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC);
|
|
|
|
int ret, i;
|
2019-04-16 15:58:53 -07:00
|
|
|
|
2021-09-30 17:17:39 +01:00
|
|
|
*container = kcalloc(1, size, GFP_KERNEL);
|
|
|
|
if (!*container) {
|
|
|
|
DRM_ERROR("Cannot allocate memory for v3d job.");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
job = *container;
|
2019-04-16 15:58:53 -07:00
|
|
|
job->v3d = v3d;
|
|
|
|
job->free = free;
|
|
|
|
|
2020-04-15 09:39:44 +02:00
|
|
|
ret = pm_runtime_get_sync(v3d->drm.dev);
|
2019-04-16 15:58:53 -07:00
|
|
|
if (ret < 0)
|
2021-09-30 17:17:39 +01:00
|
|
|
goto fail;
|
2019-04-16 15:58:53 -07:00
|
|
|
|
2021-08-05 12:46:54 +02:00
|
|
|
ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue],
|
|
|
|
v3d_priv);
|
|
|
|
if (ret)
|
2021-09-30 17:17:39 +01:00
|
|
|
goto fail_job;
|
2019-04-16 15:58:56 -07:00
|
|
|
|
2021-09-30 17:19:56 +01:00
|
|
|
if (has_multisync) {
|
|
|
|
if (se->in_sync_count && se->wait_stage == queue) {
|
|
|
|
struct drm_v3d_sem __user *handle = u64_to_user_ptr(se->in_syncs);
|
|
|
|
|
|
|
|
for (i = 0; i < se->in_sync_count; i++) {
|
|
|
|
struct drm_v3d_sem in;
|
|
|
|
|
2021-10-11 15:33:03 +03:00
|
|
|
if (copy_from_user(&in, handle++, sizeof(in))) {
|
|
|
|
ret = -EFAULT;
|
2021-09-30 17:19:56 +01:00
|
|
|
DRM_DEBUG("Failed to copy wait dep handle.\n");
|
|
|
|
goto fail_deps;
|
|
|
|
}
|
|
|
|
ret = v3d_job_add_deps(file_priv, job, in.handle, 0);
|
|
|
|
if (ret)
|
|
|
|
goto fail_deps;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = v3d_job_add_deps(file_priv, job, in_sync, 0);
|
|
|
|
if (ret)
|
|
|
|
goto fail_deps;
|
|
|
|
}
|
2019-04-16 15:58:53 -07:00
|
|
|
|
|
|
|
kref_init(&job->refcount);
|
|
|
|
|
|
|
|
return 0;
|
2021-09-30 17:17:39 +01:00
|
|
|
|
|
|
|
fail_deps:
|
2021-08-05 12:46:54 +02:00
|
|
|
drm_sched_job_cleanup(&job->base);
|
2021-09-30 17:17:39 +01:00
|
|
|
fail_job:
|
2020-04-15 09:39:44 +02:00
|
|
|
pm_runtime_put_autosuspend(v3d->drm.dev);
|
2021-09-30 17:17:39 +01:00
|
|
|
fail:
|
|
|
|
kfree(*container);
|
|
|
|
*container = NULL;
|
|
|
|
|
2019-04-16 15:58:56 -07:00
|
|
|
return ret;
|
2019-04-16 15:58:53 -07:00
|
|
|
}
|
|
|
|
|
2021-08-05 12:46:54 +02:00
|
|
|
static void
|
|
|
|
v3d_push_job(struct v3d_job *job)
|
2019-04-16 15:58:53 -07:00
|
|
|
{
|
drm/sched: Split drm_sched_job_init
This is a very confusingly named function, because not just does it
init an object, it arms it and provides a point of no return for
pushing a job into the scheduler. It would be nice if that's a bit
clearer in the interface.
But the real reason is that I want to push the dependency tracking
helpers into the scheduler code, and that means drm_sched_job_init
must be called a lot earlier, without arming the job.
v2:
- don't change .gitignore (Steven)
- don't forget v3d (Emma)
v3: Emma noticed that I leak the memory allocated in
drm_sched_job_init if we bail out before the point of no return in
subsequent driver patches. To be able to fix this change
drm_sched_job_cleanup() so it can handle being called both before and
after drm_sched_job_arm().
Also improve the kerneldoc for this.
v4:
- Fix the drm_sched_job_cleanup logic, I inverted the booleans, as
usual (Melissa)
- Christian pointed out that drm_sched_entity_select_rq() also needs
to be moved into drm_sched_job_arm, which made me realize that the
job->id definitely needs to be moved too.
Shuffle things to fit between job_init and job_arm.
v5:
Reshuffle the split between init/arm once more, amdgpu abuses
drm_sched.ready to signal gpu reset failures. Also document this
somewhat. (Christian)
v6:
Rebase on top of the msm drm/sched support. Note that the
drm_sched_job_init() call is completely misplaced, and hence also the
split-out drm_sched_entity_push_job(). I've put in a FIXME which the next
patch will address.
v7: Drop the FIXME in msm, after discussions with Rob I agree it shouldn't
be a problem where it is now.
Acked-by: Christian König <christian.koenig@amd.com>
Acked-by: Melissa Wen <mwen@igalia.com>
Cc: Melissa Wen <melissa.srw@gmail.com>
Acked-by: Emma Anholt <emma@anholt.net>
Acked-by: Steven Price <steven.price@arm.com> (v2)
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> (v5)
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Russell King <linux+etnaviv@armlinux.org.uk>
Cc: Christian Gmeiner <christian.gmeiner@gmail.com>
Cc: Qiang Yu <yuq825@gmail.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Cc: Steven Price <steven.price@arm.com>
Cc: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Cc: David Airlie <airlied@linux.ie>
Cc: Daniel Vetter <daniel@ffwll.ch>
Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: "Christian König" <christian.koenig@amd.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Adam Borowski <kilobyte@angband.pl>
Cc: Nick Terrell <terrelln@fb.com>
Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Cc: Paul Menzel <pmenzel@molgen.mpg.de>
Cc: Sami Tolvanen <samitolvanen@google.com>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Nirmoy Das <nirmoy.das@amd.com>
Cc: Deepak R Varma <mh12gx2825@gmail.com>
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Kevin Wang <kevin1.wang@amd.com>
Cc: Chen Li <chenli@uniontech.com>
Cc: Luben Tuikov <luben.tuikov@amd.com>
Cc: "Marek Olšák" <marek.olsak@amd.com>
Cc: Dennis Li <Dennis.Li@amd.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Cc: Sonny Jiang <sonny.jiang@amd.com>
Cc: Boris Brezillon <boris.brezillon@collabora.com>
Cc: Tian Tao <tiantao6@hisilicon.com>
Cc: etnaviv@lists.freedesktop.org
Cc: lima@lists.freedesktop.org
Cc: linux-media@vger.kernel.org
Cc: linaro-mm-sig@lists.linaro.org
Cc: Emma Anholt <emma@anholt.net>
Cc: Rob Clark <robdclark@gmail.com>
Cc: Sean Paul <sean@poorly.run>
Cc: linux-arm-msm@vger.kernel.org
Cc: freedreno@lists.freedesktop.org
Link: https://patchwork.freedesktop.org/patch/msgid/20210817084917.3555822-1-daniel.vetter@ffwll.ch
2021-08-17 10:49:16 +02:00
|
|
|
drm_sched_job_arm(&job->base);
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
job->done_fence = dma_fence_get(&job->base.s_fence->finished);
|
|
|
|
|
|
|
|
/* put by scheduler job completion */
|
|
|
|
kref_get(&job->refcount);
|
|
|
|
|
2021-08-05 12:46:50 +02:00
|
|
|
drm_sched_entity_push_job(&job->base);
|
2019-04-16 15:58:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv,
|
|
|
|
struct v3d_job *job,
|
|
|
|
struct ww_acquire_ctx *acquire_ctx,
|
2019-04-16 15:58:54 -07:00
|
|
|
u32 out_sync,
|
2021-09-30 17:19:56 +01:00
|
|
|
struct v3d_submit_ext *se,
|
2019-04-16 15:58:54 -07:00
|
|
|
struct dma_fence *done_fence)
|
2019-04-16 15:58:53 -07:00
|
|
|
{
|
|
|
|
struct drm_syncobj *sync_out;
|
2021-09-30 17:19:56 +01:00
|
|
|
bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC);
|
2019-04-16 15:58:53 -07:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < job->bo_count; i++) {
|
|
|
|
/* XXX: Use shared fences for read-only objects. */
|
2019-08-11 10:06:32 +02:00
|
|
|
dma_resv_add_excl_fence(job->bo[i]->resv,
|
2021-09-30 17:15:22 +01:00
|
|
|
job->done_fence);
|
2019-04-16 15:58:53 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx);
|
|
|
|
|
|
|
|
/* Update the return sync object for the job */
|
2021-09-30 17:19:56 +01:00
|
|
|
/* If it only supports a single signal semaphore*/
|
|
|
|
if (!has_multisync) {
|
|
|
|
sync_out = drm_syncobj_find(file_priv, out_sync);
|
|
|
|
if (sync_out) {
|
|
|
|
drm_syncobj_replace_fence(sync_out, done_fence);
|
|
|
|
drm_syncobj_put(sync_out);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If multiple semaphores extension is supported */
|
|
|
|
if (se->out_sync_count) {
|
|
|
|
for (i = 0; i < se->out_sync_count; i++) {
|
|
|
|
drm_syncobj_replace_fence(se->out_syncs[i].syncobj,
|
|
|
|
done_fence);
|
|
|
|
drm_syncobj_put(se->out_syncs[i].syncobj);
|
|
|
|
}
|
|
|
|
kvfree(se->out_syncs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3d_put_multisync_post_deps(struct v3d_submit_ext *se)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
if (!(se && se->out_sync_count))
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < se->out_sync_count; i++)
|
|
|
|
drm_syncobj_put(se->out_syncs[i].syncobj);
|
|
|
|
kvfree(se->out_syncs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
v3d_get_multisync_post_deps(struct drm_file *file_priv,
|
|
|
|
struct v3d_submit_ext *se,
|
|
|
|
u32 count, u64 handles)
|
|
|
|
{
|
|
|
|
struct drm_v3d_sem __user *post_deps;
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
if (!count)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
se->out_syncs = (struct v3d_submit_outsync *)
|
|
|
|
kvmalloc_array(count,
|
|
|
|
sizeof(struct v3d_submit_outsync),
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!se->out_syncs)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
post_deps = u64_to_user_ptr(handles);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
struct drm_v3d_sem out;
|
|
|
|
|
2021-10-11 15:33:03 +03:00
|
|
|
if (copy_from_user(&out, post_deps++, sizeof(out))) {
|
|
|
|
ret = -EFAULT;
|
2021-09-30 17:19:56 +01:00
|
|
|
DRM_DEBUG("Failed to copy post dep handles\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
se->out_syncs[i].syncobj = drm_syncobj_find(file_priv,
|
|
|
|
out.handle);
|
|
|
|
if (!se->out_syncs[i].syncobj) {
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
2019-04-16 15:58:53 -07:00
|
|
|
}
|
2021-09-30 17:19:56 +01:00
|
|
|
se->out_sync_count = count;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
for (i--; i >= 0; i--)
|
|
|
|
drm_syncobj_put(se->out_syncs[i].syncobj);
|
|
|
|
kvfree(se->out_syncs);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get data for multiple binary semaphores synchronization. Parse syncobj
|
|
|
|
* to be signaled when job completes (out_sync).
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
v3d_get_multisync_submit_deps(struct drm_file *file_priv,
|
|
|
|
struct drm_v3d_extension __user *ext,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct drm_v3d_multi_sync multisync;
|
|
|
|
struct v3d_submit_ext *se = data;
|
|
|
|
int ret;
|
|
|
|
|
2021-10-11 15:33:03 +03:00
|
|
|
if (copy_from_user(&multisync, ext, sizeof(multisync)))
|
|
|
|
return -EFAULT;
|
2021-09-30 17:19:56 +01:00
|
|
|
|
|
|
|
if (multisync.pad)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
ret = v3d_get_multisync_post_deps(file_priv, data, multisync.out_sync_count,
|
|
|
|
multisync.out_syncs);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
se->in_sync_count = multisync.in_sync_count;
|
|
|
|
se->in_syncs = multisync.in_syncs;
|
|
|
|
se->flags |= DRM_V3D_EXT_ID_MULTI_SYNC;
|
|
|
|
se->wait_stage = multisync.wait_stage;
|
|
|
|
|
|
|
|
return 0;
|
2019-04-16 15:58:53 -07:00
|
|
|
}
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
/* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data
|
|
|
|
* according to the extension id (name).
|
|
|
|
*/
|
|
|
|
static int
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_get_extensions(struct drm_file *file_priv,
|
|
|
|
u64 ext_handles,
|
|
|
|
void *data)
|
2021-09-30 17:18:50 +01:00
|
|
|
{
|
|
|
|
struct drm_v3d_extension __user *user_ext;
|
2021-09-30 17:19:56 +01:00
|
|
|
int ret;
|
2021-09-30 17:18:50 +01:00
|
|
|
|
|
|
|
user_ext = u64_to_user_ptr(ext_handles);
|
|
|
|
while (user_ext) {
|
|
|
|
struct drm_v3d_extension ext;
|
|
|
|
|
|
|
|
if (copy_from_user(&ext, user_ext, sizeof(ext))) {
|
|
|
|
DRM_DEBUG("Failed to copy submit extension\n");
|
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ext.id) {
|
2021-09-30 17:19:56 +01:00
|
|
|
case DRM_V3D_EXT_ID_MULTI_SYNC:
|
|
|
|
ret = v3d_get_multisync_submit_deps(file_priv, user_ext, data);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
break;
|
2021-09-30 17:18:50 +01:00
|
|
|
default:
|
|
|
|
DRM_DEBUG_DRIVER("Unknown extension id: %d\n", ext.id);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
user_ext = u64_to_user_ptr(ext.next);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-30 11:10:58 -07:00
|
|
|
/**
|
|
|
|
* v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D.
|
|
|
|
* @dev: DRM device
|
|
|
|
* @data: ioctl argument
|
|
|
|
* @file_priv: DRM file for this fd
|
|
|
|
*
|
|
|
|
* This is the main entrypoint for userspace to submit a 3D frame to
|
|
|
|
* the GPU. Userspace provides the binner command list (if
|
|
|
|
* applicable), and the kernel sets up the render command list to draw
|
|
|
|
* to the framebuffer described in the ioctl, using the command lists
|
|
|
|
* that the 3D engine's binner will produce.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv)
|
|
|
|
{
|
|
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
|
|
|
struct drm_v3d_submit_cl *args = data;
|
2021-09-30 17:19:56 +01:00
|
|
|
struct v3d_submit_ext se = {0};
|
2019-04-16 15:58:53 -07:00
|
|
|
struct v3d_bin_job *bin = NULL;
|
2021-09-30 17:17:39 +01:00
|
|
|
struct v3d_render_job *render = NULL;
|
2019-09-19 09:10:16 +02:00
|
|
|
struct v3d_job *clean_job = NULL;
|
|
|
|
struct v3d_job *last_job;
|
2018-04-30 11:10:58 -07:00
|
|
|
struct ww_acquire_ctx acquire_ctx;
|
|
|
|
int ret = 0;
|
|
|
|
|
2018-11-30 16:57:58 -08:00
|
|
|
trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
if (args->pad)
|
2021-06-08 13:15:41 +02:00
|
|
|
return -EINVAL;
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
if (args->flags &&
|
|
|
|
args->flags & ~(DRM_V3D_SUBMIT_CL_FLUSH_CACHE |
|
|
|
|
DRM_V3D_SUBMIT_EXTENSION)) {
|
2019-09-19 09:10:16 +02:00
|
|
|
DRM_INFO("invalid flags: %d\n", args->flags);
|
2018-04-30 11:10:58 -07:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
if (args->flags & DRM_V3D_SUBMIT_EXTENSION) {
|
2021-09-30 17:19:56 +01:00
|
|
|
ret = v3d_get_extensions(file_priv, args->extensions, &se);
|
2021-09-30 17:18:50 +01:00
|
|
|
if (ret) {
|
|
|
|
DRM_DEBUG("Failed to get extensions.\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = v3d_job_init(v3d, file_priv, (void *)&render, sizeof(*render),
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_render_job_free, args->in_sync_rcl, &se, V3D_RENDER);
|
2021-09-30 17:17:39 +01:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
render->start = args->rcl_start;
|
|
|
|
render->end = args->rcl_end;
|
|
|
|
INIT_LIST_HEAD(&render->unref_list);
|
|
|
|
|
|
|
|
if (args->bcl_start != args->bcl_end) {
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = v3d_job_init(v3d, file_priv, (void *)&bin, sizeof(*bin),
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_job_free, args->in_sync_bcl, &se, V3D_BIN);
|
2021-09-30 17:17:39 +01:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
bin->start = args->bcl_start;
|
|
|
|
bin->end = args->bcl_end;
|
|
|
|
bin->qma = args->qma;
|
|
|
|
bin->qms = args->qms;
|
|
|
|
bin->qts = args->qts;
|
|
|
|
bin->render = render;
|
|
|
|
}
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-09-19 09:10:16 +02:00
|
|
|
if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) {
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = v3d_job_init(v3d, file_priv, (void *)&clean_job, sizeof(*clean_job),
|
2021-10-15 15:14:41 +08:00
|
|
|
v3d_job_free, 0, NULL, V3D_CACHE_CLEAN);
|
2021-09-30 17:17:39 +01:00
|
|
|
if (ret)
|
2019-09-19 09:10:16 +02:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
last_job = clean_job;
|
|
|
|
} else {
|
|
|
|
last_job = &render->base;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = v3d_lookup_bos(dev, file_priv, last_job,
|
2019-04-16 15:58:53 -07:00
|
|
|
args->bo_handles, args->bo_handle_count);
|
2018-04-30 11:10:58 -07:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2019-09-19 09:10:16 +02:00
|
|
|
ret = v3d_lock_bo_reservations(last_job, &acquire_ctx);
|
2018-04-30 11:10:58 -07:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2021-06-08 13:15:41 +02:00
|
|
|
if (args->perfmon_id) {
|
|
|
|
render->base.perfmon = v3d_perfmon_find(v3d_priv,
|
|
|
|
args->perfmon_id);
|
|
|
|
|
|
|
|
if (!render->base.perfmon) {
|
|
|
|
ret = -ENOENT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-06 10:48:51 -07:00
|
|
|
mutex_lock(&v3d->sched_lock);
|
2019-04-16 15:58:53 -07:00
|
|
|
if (bin) {
|
2021-06-08 13:15:41 +02:00
|
|
|
bin->base.perfmon = render->base.perfmon;
|
|
|
|
v3d_perfmon_get(bin->base.perfmon);
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_push_job(&bin->base);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2021-08-05 12:46:55 +02:00
|
|
|
ret = drm_sched_job_add_dependency(&render->base.base,
|
|
|
|
dma_fence_get(bin->base.done_fence));
|
2019-04-16 15:58:56 -07:00
|
|
|
if (ret)
|
|
|
|
goto fail_unreserve;
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|
|
|
|
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_push_job(&render->base);
|
2019-09-19 09:10:16 +02:00
|
|
|
|
|
|
|
if (clean_job) {
|
|
|
|
struct dma_fence *render_fence =
|
|
|
|
dma_fence_get(render->base.done_fence);
|
2021-08-05 12:46:55 +02:00
|
|
|
ret = drm_sched_job_add_dependency(&clean_job->base,
|
|
|
|
render_fence);
|
2019-09-19 09:10:16 +02:00
|
|
|
if (ret)
|
|
|
|
goto fail_unreserve;
|
2021-06-08 13:15:41 +02:00
|
|
|
clean_job->perfmon = render->base.perfmon;
|
|
|
|
v3d_perfmon_get(clean_job->perfmon);
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_push_job(clean_job);
|
2019-09-19 09:10:16 +02:00
|
|
|
}
|
|
|
|
|
2018-06-06 10:48:51 -07:00
|
|
|
mutex_unlock(&v3d->sched_lock);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_attach_fences_and_unlock_reservation(file_priv,
|
2019-09-19 09:10:16 +02:00
|
|
|
last_job,
|
2019-04-16 15:58:54 -07:00
|
|
|
&acquire_ctx,
|
|
|
|
args->out_sync,
|
2021-09-30 17:19:56 +01:00
|
|
|
&se,
|
2019-09-19 09:10:16 +02:00
|
|
|
last_job->done_fence);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
if (bin)
|
|
|
|
v3d_job_put(&bin->base);
|
|
|
|
v3d_job_put(&render->base);
|
2019-09-19 09:10:16 +02:00
|
|
|
if (clean_job)
|
|
|
|
v3d_job_put(clean_job);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail_unreserve:
|
2018-06-06 10:48:51 -07:00
|
|
|
mutex_unlock(&v3d->sched_lock);
|
2019-09-19 09:10:16 +02:00
|
|
|
drm_gem_unlock_reservations(last_job->bo,
|
|
|
|
last_job->bo_count, &acquire_ctx);
|
2018-04-30 11:10:58 -07:00
|
|
|
fail:
|
2021-09-30 17:17:39 +01:00
|
|
|
v3d_job_cleanup((void *)bin);
|
|
|
|
v3d_job_cleanup((void *)render);
|
|
|
|
v3d_job_cleanup(clean_job);
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_put_multisync_post_deps(&se);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
/**
|
|
|
|
* v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D.
|
|
|
|
* @dev: DRM device
|
|
|
|
* @data: ioctl argument
|
|
|
|
* @file_priv: DRM file for this fd
|
|
|
|
*
|
|
|
|
* Userspace provides the register setup for the TFU, which we don't
|
|
|
|
* need to validate since the TFU is behind the MMU.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
v3d_submit_tfu_ioctl(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv)
|
|
|
|
{
|
|
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
|
|
struct drm_v3d_submit_tfu *args = data;
|
2021-09-30 17:19:56 +01:00
|
|
|
struct v3d_submit_ext se = {0};
|
2021-09-30 17:17:39 +01:00
|
|
|
struct v3d_tfu_job *job = NULL;
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
struct ww_acquire_ctx acquire_ctx;
|
|
|
|
int ret = 0;
|
|
|
|
|
2018-11-30 16:57:58 -08:00
|
|
|
trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) {
|
|
|
|
DRM_DEBUG("invalid flags: %d\n", args->flags);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args->flags & DRM_V3D_SUBMIT_EXTENSION) {
|
2021-09-30 17:19:56 +01:00
|
|
|
ret = v3d_get_extensions(file_priv, args->extensions, &se);
|
2021-09-30 17:18:50 +01:00
|
|
|
if (ret) {
|
|
|
|
DRM_DEBUG("Failed to get extensions.\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job),
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_job_free, args->in_sync, &se, V3D_TFU);
|
2021-09-30 17:17:39 +01:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles),
|
|
|
|
sizeof(*job->base.bo), GFP_KERNEL);
|
|
|
|
if (!job->base.bo) {
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = -ENOMEM;
|
|
|
|
goto fail;
|
2019-04-16 15:58:53 -07:00
|
|
|
}
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
|
|
|
|
job->args = *args;
|
|
|
|
|
|
|
|
spin_lock(&file_priv->table_lock);
|
2019-04-16 15:58:53 -07:00
|
|
|
for (job->base.bo_count = 0;
|
|
|
|
job->base.bo_count < ARRAY_SIZE(args->bo_handles);
|
|
|
|
job->base.bo_count++) {
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
struct drm_gem_object *bo;
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
if (!args->bo_handles[job->base.bo_count])
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
bo = idr_find(&file_priv->object_idr,
|
2019-04-16 15:58:53 -07:00
|
|
|
args->bo_handles[job->base.bo_count]);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
if (!bo) {
|
|
|
|
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
|
2019-04-16 15:58:53 -07:00
|
|
|
job->base.bo_count,
|
|
|
|
args->bo_handles[job->base.bo_count]);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
ret = -ENOENT;
|
|
|
|
spin_unlock(&file_priv->table_lock);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
drm_gem_object_get(bo);
|
2019-04-16 15:58:53 -07:00
|
|
|
job->base.bo[job->base.bo_count] = bo;
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
}
|
|
|
|
spin_unlock(&file_priv->table_lock);
|
|
|
|
|
2019-04-16 15:58:56 -07:00
|
|
|
ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
mutex_lock(&v3d->sched_lock);
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_push_job(&job->base);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
mutex_unlock(&v3d->sched_lock);
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_attach_fences_and_unlock_reservation(file_priv,
|
|
|
|
&job->base, &acquire_ctx,
|
2019-04-16 15:58:54 -07:00
|
|
|
args->out_sync,
|
2021-09-30 17:19:56 +01:00
|
|
|
&se,
|
2019-04-16 15:58:54 -07:00
|
|
|
job->base.done_fence);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
v3d_job_put(&job->base);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail:
|
2021-09-30 17:17:39 +01:00
|
|
|
v3d_job_cleanup((void *)job);
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_put_multisync_post_deps(&se);
|
drm/v3d: Add support for submitting jobs to the TFU.
The TFU can copy from raster, UIF, and SAND input images to UIF output
images, with optional mipmap generation. This will certainly be
useful for media EGL image input, but is also useful immediately for
mipmap generation without bogging the V3D core down.
For now we only run the queue 1 job deep, and don't have any hang
recovery (though I don't think we should need it, with TFU). Queuing
multiple jobs in the HW will require synchronizing the YUV coefficient
regs updates since they don't get FIFOed with the job.
v2: Change the ioctl to IOW instead of IOWR, always set COEF0, explain
why TFU is AUTH, clarify the syncing docs, drop the unused TFU
interrupt regs (you're expected to use the hub's), don't take
&bo->base for NULL bos.
v3: Fix a little whitespace alignment (noticed by checkpatch), rebase
on drm_sched_job_cleanup() changes.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Emett <david.emett@broadcom.com> (v2)
Link: https://patchwork.freedesktop.org/patch/264607/
2018-11-28 15:09:25 -08:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:54 -07:00
|
|
|
/**
|
|
|
|
* v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D.
|
|
|
|
* @dev: DRM device
|
|
|
|
* @data: ioctl argument
|
|
|
|
* @file_priv: DRM file for this fd
|
|
|
|
*
|
|
|
|
* Userspace provides the register setup for the CSD, which we don't
|
|
|
|
* need to validate since the CSD is behind the MMU.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
v3d_submit_csd_ioctl(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file_priv)
|
|
|
|
{
|
|
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
|
|
struct v3d_file_priv *v3d_priv = file_priv->driver_priv;
|
|
|
|
struct drm_v3d_submit_csd *args = data;
|
2021-09-30 17:19:56 +01:00
|
|
|
struct v3d_submit_ext se = {0};
|
2021-09-30 17:17:39 +01:00
|
|
|
struct v3d_csd_job *job = NULL;
|
|
|
|
struct v3d_job *clean_job = NULL;
|
2019-04-16 15:58:54 -07:00
|
|
|
struct ww_acquire_ctx acquire_ctx;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]);
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
if (args->pad)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2019-04-16 15:58:54 -07:00
|
|
|
if (!v3d_has_csd(v3d)) {
|
|
|
|
DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:18:50 +01:00
|
|
|
if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) {
|
|
|
|
DRM_INFO("invalid flags: %d\n", args->flags);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (args->flags & DRM_V3D_SUBMIT_EXTENSION) {
|
2021-09-30 17:19:56 +01:00
|
|
|
ret = v3d_get_extensions(file_priv, args->extensions, &se);
|
2021-09-30 17:18:50 +01:00
|
|
|
if (ret) {
|
|
|
|
DRM_DEBUG("Failed to get extensions.\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job),
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_job_free, args->in_sync, &se, V3D_CSD);
|
2021-09-30 17:17:39 +01:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
2019-04-16 15:58:54 -07:00
|
|
|
|
2021-09-30 17:17:39 +01:00
|
|
|
ret = v3d_job_init(v3d, file_priv, (void *)&clean_job, sizeof(*clean_job),
|
2021-10-15 15:14:41 +08:00
|
|
|
v3d_job_free, 0, NULL, V3D_CACHE_CLEAN);
|
2021-09-30 17:17:39 +01:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
2019-04-16 15:58:54 -07:00
|
|
|
|
|
|
|
job->args = *args;
|
|
|
|
|
|
|
|
ret = v3d_lookup_bos(dev, file_priv, clean_job,
|
|
|
|
args->bo_handles, args->bo_handle_count);
|
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2019-04-16 15:58:56 -07:00
|
|
|
ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx);
|
2019-04-16 15:58:54 -07:00
|
|
|
if (ret)
|
|
|
|
goto fail;
|
|
|
|
|
2021-06-08 13:15:41 +02:00
|
|
|
if (args->perfmon_id) {
|
|
|
|
job->base.perfmon = v3d_perfmon_find(v3d_priv,
|
|
|
|
args->perfmon_id);
|
|
|
|
if (!job->base.perfmon) {
|
|
|
|
ret = -ENOENT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-16 15:58:54 -07:00
|
|
|
mutex_lock(&v3d->sched_lock);
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_push_job(&job->base);
|
2019-04-16 15:58:54 -07:00
|
|
|
|
2021-08-05 12:46:55 +02:00
|
|
|
ret = drm_sched_job_add_dependency(&clean_job->base,
|
|
|
|
dma_fence_get(job->base.done_fence));
|
2019-04-16 15:58:56 -07:00
|
|
|
if (ret)
|
|
|
|
goto fail_unreserve;
|
|
|
|
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_push_job(clean_job);
|
2019-04-16 15:58:54 -07:00
|
|
|
mutex_unlock(&v3d->sched_lock);
|
|
|
|
|
|
|
|
v3d_attach_fences_and_unlock_reservation(file_priv,
|
|
|
|
clean_job,
|
|
|
|
&acquire_ctx,
|
|
|
|
args->out_sync,
|
2021-09-30 17:19:56 +01:00
|
|
|
&se,
|
2019-04-16 15:58:54 -07:00
|
|
|
clean_job->done_fence);
|
|
|
|
|
|
|
|
v3d_job_put(&job->base);
|
|
|
|
v3d_job_put(clean_job);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
fail_unreserve:
|
|
|
|
mutex_unlock(&v3d->sched_lock);
|
|
|
|
drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count,
|
|
|
|
&acquire_ctx);
|
|
|
|
fail:
|
2021-09-30 17:17:39 +01:00
|
|
|
v3d_job_cleanup((void *)job);
|
2021-08-05 12:46:54 +02:00
|
|
|
v3d_job_cleanup(clean_job);
|
2021-09-30 17:19:56 +01:00
|
|
|
v3d_put_multisync_post_deps(&se);
|
2019-04-16 15:58:54 -07:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-04-30 11:10:58 -07:00
|
|
|
int
|
|
|
|
v3d_gem_init(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
|
|
u32 pt_size = 4096 * 1024;
|
|
|
|
int ret, i;
|
|
|
|
|
|
|
|
for (i = 0; i < V3D_MAX_QUEUES; i++)
|
|
|
|
v3d->queue[i].fence_context = dma_fence_context_alloc(1);
|
|
|
|
|
|
|
|
spin_lock_init(&v3d->mm_lock);
|
|
|
|
spin_lock_init(&v3d->job_lock);
|
|
|
|
mutex_init(&v3d->bo_lock);
|
|
|
|
mutex_init(&v3d->reset_lock);
|
2018-06-06 10:48:51 -07:00
|
|
|
mutex_init(&v3d->sched_lock);
|
2019-04-16 15:58:54 -07:00
|
|
|
mutex_init(&v3d->cache_clean_lock);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
/* Note: We don't allocate address 0. Various bits of HW
|
|
|
|
* treat 0 as special, such as the occlusion query counters
|
|
|
|
* where 0 means "disabled".
|
|
|
|
*/
|
|
|
|
drm_mm_init(&v3d->mm, 1, pt_size / sizeof(u32) - 1);
|
|
|
|
|
2020-04-15 09:39:44 +02:00
|
|
|
v3d->pt = dma_alloc_wc(v3d->drm.dev, pt_size,
|
2018-04-30 11:10:58 -07:00
|
|
|
&v3d->pt_paddr,
|
|
|
|
GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
|
|
|
|
if (!v3d->pt) {
|
|
|
|
drm_mm_takedown(&v3d->mm);
|
2020-04-15 09:39:44 +02:00
|
|
|
dev_err(v3d->drm.dev,
|
2021-09-30 17:15:22 +01:00
|
|
|
"Failed to allocate page tables. Please ensure you have CMA enabled.\n");
|
2018-04-30 11:10:58 -07:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
v3d_init_hw_state(v3d);
|
|
|
|
v3d_mmu_set_page_table(v3d);
|
|
|
|
|
|
|
|
ret = v3d_sched_init(v3d);
|
|
|
|
if (ret) {
|
|
|
|
drm_mm_takedown(&v3d->mm);
|
2020-04-15 09:39:44 +02:00
|
|
|
dma_free_coherent(v3d->drm.dev, 4096 * 1024, (void *)v3d->pt,
|
2018-04-30 11:10:58 -07:00
|
|
|
v3d->pt_paddr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3d_gem_destroy(struct drm_device *dev)
|
|
|
|
{
|
|
|
|
struct v3d_dev *v3d = to_v3d_dev(dev);
|
|
|
|
|
|
|
|
v3d_sched_fini(v3d);
|
|
|
|
|
2019-04-16 15:58:53 -07:00
|
|
|
/* Waiting for jobs to finish would need to be done before
|
2018-04-30 11:10:58 -07:00
|
|
|
* unregistering V3D.
|
|
|
|
*/
|
2018-06-05 12:03:01 -07:00
|
|
|
WARN_ON(v3d->bin_job);
|
|
|
|
WARN_ON(v3d->render_job);
|
2018-04-30 11:10:58 -07:00
|
|
|
|
|
|
|
drm_mm_takedown(&v3d->mm);
|
|
|
|
|
2020-04-15 09:39:44 +02:00
|
|
|
dma_free_coherent(v3d->drm.dev, 4096 * 1024, (void *)v3d->pt,
|
|
|
|
v3d->pt_paddr);
|
2018-04-30 11:10:58 -07:00
|
|
|
}
|