Merge tag 'drm-misc-next-fixes-2021-09-09' of git://anongit.freedesktop.org/drm/drm...
[linux-2.6-microblaze.git] / drivers / gpu / drm / tegra / drm.c
index f96c237..8d37d6b 100644 (file)
 #include <drm/drm_prime.h>
 #include <drm/drm_vblank.h>
 
+#include "dc.h"
 #include "drm.h"
 #include "gem.h"
+#include "uapi.h"
 
 #define DRIVER_NAME "tegra"
 #define DRIVER_DESC "NVIDIA Tegra graphics"
 #define DRIVER_DATE "20120330"
-#define DRIVER_MAJOR 0
+#define DRIVER_MAJOR 1
 #define DRIVER_MINOR 0
 #define DRIVER_PATCHLEVEL 0
 
 #define CARVEOUT_SZ SZ_64M
 #define CDMA_GATHER_FETCHES_MAX_NB 16383
 
-struct tegra_drm_file {
-       struct idr contexts;
-       struct mutex lock;
-};
-
 static int tegra_atomic_check(struct drm_device *drm,
                              struct drm_atomic_state *state)
 {
@@ -60,6 +57,17 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
        .atomic_commit = drm_atomic_helper_commit,
 };
 
+static void tegra_atomic_post_commit(struct drm_device *drm,
+                                    struct drm_atomic_state *old_state)
+{
+       struct drm_crtc_state *old_crtc_state __maybe_unused;
+       struct drm_crtc *crtc;
+       unsigned int i;
+
+       for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i)
+               tegra_crtc_atomic_post_commit(crtc, old_state);
+}
+
 static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
 {
        struct drm_device *drm = old_state->dev;
@@ -79,6 +87,8 @@ static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
        } else {
                drm_atomic_helper_commit_tail_rpm(old_state);
        }
+
+       tegra_atomic_post_commit(drm, old_state);
 }
 
 static const struct drm_mode_config_helper_funcs
@@ -94,7 +104,9 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp)
        if (!fpriv)
                return -ENOMEM;
 
-       idr_init_base(&fpriv->contexts, 1);
+       idr_init_base(&fpriv->legacy_contexts, 1);
+       xa_init_flags(&fpriv->contexts, XA_FLAGS_ALLOC1);
+       xa_init(&fpriv->syncpoints);
        mutex_init(&fpriv->lock);
        filp->driver_priv = fpriv;
 
@@ -107,20 +119,6 @@ static void tegra_drm_context_free(struct tegra_drm_context *context)
        kfree(context);
 }
 
-static struct host1x_bo *
-host1x_bo_lookup(struct drm_file *file, u32 handle)
-{
-       struct drm_gem_object *gem;
-       struct tegra_bo *bo;
-
-       gem = drm_gem_object_lookup(file, handle);
-       if (!gem)
-               return NULL;
-
-       bo = to_tegra_bo(gem);
-       return &bo->base;
-}
-
 static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
                                       struct drm_tegra_reloc __user *src,
                                       struct drm_device *drm,
@@ -151,11 +149,11 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
 
        dest->flags = HOST1X_RELOC_READ | HOST1X_RELOC_WRITE;
 
-       dest->cmdbuf.bo = host1x_bo_lookup(file, cmdbuf);
+       dest->cmdbuf.bo = tegra_gem_lookup(file, cmdbuf);
        if (!dest->cmdbuf.bo)
                return -ENOENT;
 
-       dest->target.bo = host1x_bo_lookup(file, target);
+       dest->target.bo = tegra_gem_lookup(file, target);
        if (!dest->target.bo)
                return -ENOENT;
 
@@ -193,7 +191,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                return -EINVAL;
 
        job = host1x_job_alloc(context->channel, args->num_cmdbufs,
-                              args->num_relocs);
+                              args->num_relocs, false);
        if (!job)
                return -ENOMEM;
 
@@ -201,6 +199,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
        job->client = client;
        job->class = client->class;
        job->serialize = true;
+       job->syncpt_recovery = true;
 
        /*
         * Track referenced BOs so that they can be unreferenced after the
@@ -237,7 +236,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
                        goto fail;
                }
 
-               bo = host1x_bo_lookup(file, cmdbuf.handle);
+               bo = tegra_gem_lookup(file, cmdbuf.handle);
                if (!bo) {
                        err = -ENOENT;
                        goto fail;
@@ -432,7 +431,7 @@ static int tegra_client_open(struct tegra_drm_file *fpriv,
        if (err < 0)
                return err;
 
-       err = idr_alloc(&fpriv->contexts, context, 1, 0, GFP_KERNEL);
+       err = idr_alloc(&fpriv->legacy_contexts, context, 1, 0, GFP_KERNEL);
        if (err < 0) {
                client->ops->close_channel(context);
                return err;
@@ -487,13 +486,13 @@ static int tegra_close_channel(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = idr_find(&fpriv->contexts, args->context);
+       context = idr_find(&fpriv->legacy_contexts, args->context);
        if (!context) {
                err = -EINVAL;
                goto unlock;
        }
 
-       idr_remove(&fpriv->contexts, context->id);
+       idr_remove(&fpriv->legacy_contexts, context->id);
        tegra_drm_context_free(context);
 
 unlock:
@@ -512,7 +511,7 @@ static int tegra_get_syncpt(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = idr_find(&fpriv->contexts, args->context);
+       context = idr_find(&fpriv->legacy_contexts, args->context);
        if (!context) {
                err = -ENODEV;
                goto unlock;
@@ -541,7 +540,7 @@ static int tegra_submit(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = idr_find(&fpriv->contexts, args->context);
+       context = idr_find(&fpriv->legacy_contexts, args->context);
        if (!context) {
                err = -ENODEV;
                goto unlock;
@@ -566,7 +565,7 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
 
        mutex_lock(&fpriv->lock);
 
-       context = idr_find(&fpriv->contexts, args->context);
+       context = idr_find(&fpriv->legacy_contexts, args->context);
        if (!context) {
                err = -ENODEV;
                goto unlock;
@@ -735,10 +734,25 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
 
 static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
 #ifdef CONFIG_DRM_TEGRA_STAGING
-       DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create,
+       DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_OPEN, tegra_drm_ioctl_channel_open,
+                         DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_CLOSE, tegra_drm_ioctl_channel_close,
+                         DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_MAP, tegra_drm_ioctl_channel_map,
+                         DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_UNMAP, tegra_drm_ioctl_channel_unmap,
                          DRM_RENDER_ALLOW),
-       DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap,
+       DRM_IOCTL_DEF_DRV(TEGRA_CHANNEL_SUBMIT, tegra_drm_ioctl_channel_submit,
                          DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_ALLOCATE, tegra_drm_ioctl_syncpoint_allocate,
+                         DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_FREE, tegra_drm_ioctl_syncpoint_free,
+                         DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_SYNCPOINT_WAIT, tegra_drm_ioctl_syncpoint_wait,
+                         DRM_RENDER_ALLOW),
+
+       DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_RENDER_ALLOW),
+       DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read,
                          DRM_RENDER_ALLOW),
        DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr,
@@ -792,10 +806,11 @@ static void tegra_drm_postclose(struct drm_device *drm, struct drm_file *file)
        struct tegra_drm_file *fpriv = file->driver_priv;
 
        mutex_lock(&fpriv->lock);
-       idr_for_each(&fpriv->contexts, tegra_drm_context_cleanup, NULL);
+       idr_for_each(&fpriv->legacy_contexts, tegra_drm_context_cleanup, NULL);
+       tegra_drm_uapi_close_file(fpriv);
        mutex_unlock(&fpriv->lock);
 
-       idr_destroy(&fpriv->contexts);
+       idr_destroy(&fpriv->legacy_contexts);
        mutex_destroy(&fpriv->lock);
        kfree(fpriv);
 }
@@ -853,7 +868,7 @@ static void tegra_debugfs_init(struct drm_minor *minor)
 
 static const struct drm_driver tegra_drm_driver = {
        .driver_features = DRIVER_MODESET | DRIVER_GEM |
-                          DRIVER_ATOMIC | DRIVER_RENDER,
+                          DRIVER_ATOMIC | DRIVER_RENDER | DRIVER_SYNCOBJ,
        .open = tegra_drm_open,
        .postclose = tegra_drm_postclose,
        .lastclose = drm_fb_helper_lastclose,
@@ -883,6 +898,14 @@ static const struct drm_driver tegra_drm_driver = {
 int tegra_drm_register_client(struct tegra_drm *tegra,
                              struct tegra_drm_client *client)
 {
+       /*
+        * When MLOCKs are implemented, change to allocate a shared channel
+        * only when MLOCKs are disabled.
+        */
+       client->shared_channel = host1x_channel_request(&client->base);
+       if (!client->shared_channel)
+               return -EBUSY;
+
        mutex_lock(&tegra->clients_lock);
        list_add_tail(&client->list, &tegra->clients);
        client->drm = tegra;
@@ -899,6 +922,9 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
        client->drm = NULL;
        mutex_unlock(&tegra->clients_lock);
 
+       if (client->shared_channel)
+               host1x_channel_put(client->shared_channel);
+
        return 0;
 }
 
@@ -1188,13 +1214,6 @@ static int host1x_drm_probe(struct host1x_device *dev)
                        goto device;
        }
 
-       /*
-        * We don't use the drm_irq_install() helpers provided by the DRM
-        * core, so we need to set this manually in order to allow the
-        * DRM_IOCTL_WAIT_VBLANK to operate correctly.
-        */
-       drm->irq_enabled = true;
-
        /* syncpoints are used for full 32-bit hardware VBLANK counters */
        drm->max_vblank_count = 0xffffffff;
 
@@ -1204,7 +1223,7 @@ static int host1x_drm_probe(struct host1x_device *dev)
 
        drm_mode_config_reset(drm);
 
-       err = drm_aperture_remove_framebuffers(false, "tegradrmfb");
+       err = drm_aperture_remove_framebuffers(false, &tegra_drm_driver);
        if (err < 0)
                goto hub;