diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2015-11-03 01:21:43 (GMT) |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2015-11-03 05:02:18 (GMT) |
commit | 2621a41647fe783be809e789faa5d8b6b06c8072 (patch) | |
tree | bd0be934e8d49441e16506f6d9bf6980924cc7a3 | |
parent | 786a57ef2cebb2d09d7f152b0ed4f1da1d368073 (diff) | |
download | linux-2621a41647fe783be809e789faa5d8b6b06c8072.tar.xz |
drm/nouveau/abi16: implement limited interoperability with usif/nvif
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_abi16.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_abi16.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_usif.c | 15 |
3 files changed, 53 insertions, 2 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 998f5cb..7f50cf5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -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; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index fa1d856..841cc55 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -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) diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c index cb1182d..89dc4ce 100644 --- a/drivers/gpu/drm/nouveau/nouveau_usif.c +++ b/drivers/gpu/drm/nouveau/nouveau_usif.c @@ -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: |