drm/nouveau/abi16: implement limited interoperability with usif/nvif
authorBen Skeggs <bskeggs@redhat.com>
Tue, 3 Nov 2015 01:21:43 +0000 (11:21 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 3 Nov 2015 05:02:18 +0000 (15:02 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_abi16.h
drivers/gpu/drm/nouveau/nouveau_usif.c

index 998f5cb..7f50cf5 100644 (file)
@@ -25,6 +25,7 @@
 #include <nvif/driver.h>
 #include <nvif/ioctl.h>
 #include <nvif/class.h>
+#include <nvif/unpack.h>
 
 #include "nouveau_drm.h"
 #include "nouveau_dma.h"
@@ -347,6 +348,44 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
 }
 
 int
+nouveau_abi16_usif(struct drm_file *file_priv, void *data, u32 size)
+{
+       union {
+               struct nvif_ioctl_v0 v0;
+       } *args = data;
+       struct nouveau_abi16_chan *chan;
+       struct nouveau_abi16 *abi16;
+       int ret;
+
+       if (nvif_unpack(args->v0, 0, 0, true)) {
+               switch (args->v0.type) {
+               case NVIF_IOCTL_V0_NEW:
+               case NVIF_IOCTL_V0_MTHD:
+               case NVIF_IOCTL_V0_SCLASS:
+                       break;
+               default:
+                       return -EACCES;
+               }
+       } else
+               return ret;
+
+       if (!(abi16 = nouveau_abi16(file_priv)))
+               return -ENOMEM;
+
+       if (args->v0.token != ~0ULL) {
+               if (!(chan = nouveau_abi16_chan(abi16, args->v0.token)))
+                       return -EINVAL;
+               args->v0.object = nvif_handle(&chan->chan->user);
+               args->v0.owner  = NVIF_IOCTL_V0_OWNER_ANY;
+               return 0;
+       }
+
+       args->v0.object = nvif_handle(&abi16->device.object);
+       args->v0.owner  = NVIF_IOCTL_V0_OWNER_ANY;
+       return 0;
+}
+
+int
 nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS)
 {
        struct drm_nouveau_channel_free *req = data;
index fa1d856..841cc55 100644 (file)
@@ -37,6 +37,7 @@ struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *);
 int  nouveau_abi16_put(struct nouveau_abi16 *, int);
 void nouveau_abi16_fini(struct nouveau_abi16 *);
 s32  nouveau_abi16_swclass(struct nouveau_drm *);
+int  nouveau_abi16_usif(struct drm_file *, void *data, u32 size);
 
 #define NOUVEAU_GEM_DOMAIN_VRAM      (1 << 1)
 #define NOUVEAU_GEM_DOMAIN_GART      (1 << 2)
index cb1182d..89dc4ce 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "nouveau_drm.h"
 #include "nouveau_usif.h"
+#include "nouveau_abi16.h"
 
 #include <nvif/notify.h>
 #include <nvif/unpack.h>
@@ -316,11 +317,21 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
        } else
                goto done;
 
+       /* USIF slightly abuses some return-only ioctl members in order
+        * to provide interoperability with the older ABI16 objects
+        */
        mutex_lock(&cli->mutex);
+       if (argv->v0.route) {
+               if (ret = -EINVAL, argv->v0.route == 0xff)
+                       ret = nouveau_abi16_usif(filp, argv, argc);
+               if (ret) {
+                       mutex_unlock(&cli->mutex);
+                       goto done;
+               }
+       }
+
        switch (argv->v0.type) {
        case NVIF_IOCTL_V0_NEW:
-               /* ... except if we're creating children */
-               argv->v0.owner = NVIF_IOCTL_V0_OWNER_ANY;
                ret = usif_object_new(filp, data, size, argv, argc);
                break;
        case NVIF_IOCTL_V0_NTFY_NEW: