Merge tag 'drm-misc-next-2018-12-06' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

Final changes to drm-misc-next for v4.21:

UAPI Changes:

Core Changes:
- Add dma_fence_get_stub to dma-buf, and use it in drm/syncobj.
- Add and use DRM_MODESET_LOCK_BEGIN/END helpers.
- Small fixes to drm_atomic_helper_resume(), drm_mode_setcrtc() and
  drm_atomic_helper_commit_duplicated_state()
- Fix drm_atomic_state_helper.[c] extraction.

Driver Changes:
- Small fixes to tinydrm, vkms, meson, rcar-du, virtio, vkms,
  v3d, and pl111.
- vc4: Allow scaling and YUV formats on cursor planes.
- v3d: Enable use of the Texture Formatting Unit, and fix
  prime imports of buffers from other drivers.
- Add support for the AUO G101EVN010 panel.
- sun4i: Enable support for the H6 display engine.

Signed-off-by: Dave Airlie <airlied@redhat.com>
[airlied: added drm/v3d: fix broken build to the merge commit]
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/321be9d3-ab75-5f92-8193-e5113662edef@linux.intel.com
This commit is contained in:
Dave Airlie
2018-12-07 10:46:29 +10:00
46 changed files with 1163 additions and 517 deletions

View File

@@ -207,26 +207,26 @@ v3d_flush_caches(struct v3d_dev *v3d)
}
static void
v3d_attach_object_fences(struct v3d_exec_info *exec)
v3d_attach_object_fences(struct v3d_bo **bos, int bo_count,
struct dma_fence *fence)
{
struct dma_fence *out_fence = exec->render_done_fence;
int i;
for (i = 0; i < exec->bo_count; i++) {
for (i = 0; i < bo_count; i++) {
/* XXX: Use shared fences for read-only objects. */
reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence);
reservation_object_add_excl_fence(bos[i]->resv, fence);
}
}
static void
v3d_unlock_bo_reservations(struct drm_device *dev,
struct v3d_exec_info *exec,
v3d_unlock_bo_reservations(struct v3d_bo **bos,
int bo_count,
struct ww_acquire_ctx *acquire_ctx)
{
int i;
for (i = 0; i < exec->bo_count; i++)
ww_mutex_unlock(&exec->bo[i]->resv->lock);
for (i = 0; i < bo_count; i++)
ww_mutex_unlock(&bos[i]->resv->lock);
ww_acquire_fini(acquire_ctx);
}
@@ -239,8 +239,8 @@ v3d_unlock_bo_reservations(struct drm_device *dev,
* to v3d, so we don't attach dma-buf fences to them.
*/
static int
v3d_lock_bo_reservations(struct drm_device *dev,
struct v3d_exec_info *exec,
v3d_lock_bo_reservations(struct v3d_bo **bos,
int bo_count,
struct ww_acquire_ctx *acquire_ctx)
{
int contended_lock = -1;
@@ -250,7 +250,7 @@ v3d_lock_bo_reservations(struct drm_device *dev,
retry:
if (contended_lock != -1) {
struct v3d_bo *bo = exec->bo[contended_lock];
struct v3d_bo *bo = bos[contended_lock];
ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock,
acquire_ctx);
@@ -260,20 +260,20 @@ retry:
}
}
for (i = 0; i < exec->bo_count; i++) {
for (i = 0; i < bo_count; i++) {
if (i == contended_lock)
continue;
ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock,
ret = ww_mutex_lock_interruptible(&bos[i]->resv->lock,
acquire_ctx);
if (ret) {
int j;
for (j = 0; j < i; j++)
ww_mutex_unlock(&exec->bo[j]->resv->lock);
ww_mutex_unlock(&bos[j]->resv->lock);
if (contended_lock != -1 && contended_lock >= i) {
struct v3d_bo *bo = exec->bo[contended_lock];
struct v3d_bo *bo = bos[contended_lock];
ww_mutex_unlock(&bo->resv->lock);
}
@@ -293,10 +293,11 @@ retry:
/* Reserve space for our shared (read-only) fence references,
* before we commit the CL to the hardware.
*/
for (i = 0; i < exec->bo_count; i++) {
ret = reservation_object_reserve_shared(exec->bo[i]->resv, 1);
for (i = 0; i < bo_count; i++) {
ret = reservation_object_reserve_shared(bos[i]->resv, 1);
if (ret) {
v3d_unlock_bo_reservations(dev, exec, acquire_ctx);
v3d_unlock_bo_reservations(bos, bo_count,
acquire_ctx);
return ret;
}
}
@@ -419,6 +420,33 @@ void v3d_exec_put(struct v3d_exec_info *exec)
kref_put(&exec->refcount, v3d_exec_cleanup);
}
static void
v3d_tfu_job_cleanup(struct kref *ref)
{
struct v3d_tfu_job *job = container_of(ref, struct v3d_tfu_job,
refcount);
struct v3d_dev *v3d = job->v3d;
unsigned int i;
dma_fence_put(job->in_fence);
dma_fence_put(job->done_fence);
for (i = 0; i < ARRAY_SIZE(job->bo); i++) {
if (job->bo[i])
drm_gem_object_put_unlocked(&job->bo[i]->base);
}
pm_runtime_mark_last_busy(v3d->dev);
pm_runtime_put_autosuspend(v3d->dev);
kfree(job);
}
void v3d_tfu_job_put(struct v3d_tfu_job *job)
{
kref_put(&job->refcount, v3d_tfu_job_cleanup);
}
int
v3d_wait_bo_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -493,6 +521,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
struct drm_syncobj *sync_out;
int ret = 0;
trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end);
if (args->pad != 0) {
DRM_INFO("pad must be zero: %d\n", args->pad);
return -EINVAL;
@@ -536,7 +566,8 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
if (ret)
goto fail;
ret = v3d_lock_bo_reservations(dev, exec, &acquire_ctx);
ret = v3d_lock_bo_reservations(exec->bo, exec->bo_count,
&acquire_ctx);
if (ret)
goto fail;
@@ -570,15 +601,15 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
&v3d_priv->sched_entity[V3D_RENDER]);
mutex_unlock(&v3d->sched_lock);
v3d_attach_object_fences(exec);
v3d_attach_object_fences(exec->bo, exec->bo_count,
exec->render_done_fence);
v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
/* Update the return sync object for the */
sync_out = drm_syncobj_find(file_priv, args->out_sync);
if (sync_out) {
drm_syncobj_replace_fence(sync_out, 0,
exec->render_done_fence);
drm_syncobj_replace_fence(sync_out, exec->render_done_fence);
drm_syncobj_put(sync_out);
}
@@ -588,13 +619,121 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
fail_unreserve:
mutex_unlock(&v3d->sched_lock);
v3d_unlock_bo_reservations(dev, exec, &acquire_ctx);
v3d_unlock_bo_reservations(exec->bo, exec->bo_count, &acquire_ctx);
fail:
v3d_exec_put(exec);
return ret;
}
/**
* 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 v3d_file_priv *v3d_priv = file_priv->driver_priv;
struct drm_v3d_submit_tfu *args = data;
struct v3d_tfu_job *job;
struct ww_acquire_ctx acquire_ctx;
struct drm_syncobj *sync_out;
struct dma_fence *sched_done_fence;
int ret = 0;
int bo_count;
trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia);
job = kcalloc(1, sizeof(*job), GFP_KERNEL);
if (!job)
return -ENOMEM;
ret = pm_runtime_get_sync(v3d->dev);
if (ret < 0) {
kfree(job);
return ret;
}
kref_init(&job->refcount);
ret = drm_syncobj_find_fence(file_priv, args->in_sync,
0, 0, &job->in_fence);
if (ret == -EINVAL)
goto fail;
job->args = *args;
job->v3d = v3d;
spin_lock(&file_priv->table_lock);
for (bo_count = 0; bo_count < ARRAY_SIZE(job->bo); bo_count++) {
struct drm_gem_object *bo;
if (!args->bo_handles[bo_count])
break;
bo = idr_find(&file_priv->object_idr,
args->bo_handles[bo_count]);
if (!bo) {
DRM_DEBUG("Failed to look up GEM BO %d: %d\n",
bo_count, args->bo_handles[bo_count]);
ret = -ENOENT;
spin_unlock(&file_priv->table_lock);
goto fail;
}
drm_gem_object_get(bo);
job->bo[bo_count] = to_v3d_bo(bo);
}
spin_unlock(&file_priv->table_lock);
ret = v3d_lock_bo_reservations(job->bo, bo_count, &acquire_ctx);
if (ret)
goto fail;
mutex_lock(&v3d->sched_lock);
ret = drm_sched_job_init(&job->base,
&v3d_priv->sched_entity[V3D_TFU],
v3d_priv);
if (ret)
goto fail_unreserve;
sched_done_fence = dma_fence_get(&job->base.s_fence->finished);
kref_get(&job->refcount); /* put by scheduler job completion */
drm_sched_entity_push_job(&job->base, &v3d_priv->sched_entity[V3D_TFU]);
mutex_unlock(&v3d->sched_lock);
v3d_attach_object_fences(job->bo, bo_count, sched_done_fence);
v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
/* Update the return sync object */
sync_out = drm_syncobj_find(file_priv, args->out_sync);
if (sync_out) {
drm_syncobj_replace_fence(sync_out, sched_done_fence);
drm_syncobj_put(sync_out);
}
dma_fence_put(sched_done_fence);
v3d_tfu_job_put(job);
return 0;
fail_unreserve:
mutex_unlock(&v3d->sched_lock);
v3d_unlock_bo_reservations(job->bo, bo_count, &acquire_ctx);
fail:
v3d_tfu_job_put(job);
return ret;
}
int
v3d_gem_init(struct drm_device *dev)
{