summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2015-11-03 11:21:43 +1000
committerBen Skeggs <bskeggs@redhat.com>2015-11-03 14:57:49 +1000
commitadac7ff93a24cae2f8e4a4e66544fc326ee35924 (patch)
tree36ee12a1fb70655ae2a74863cad514b4d5ef90d6
parentda198203ed2291e2fb0549b00c312fe84fa86929 (diff)
abi16: implement limited interoperability with usif/nvif
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drm/nouveau/nouveau_abi16.c39
-rw-r--r--drm/nouveau/nouveau_abi16.h1
-rw-r--r--drm/nouveau/nouveau_usif.c15
3 files changed, 53 insertions, 2 deletions
diff --git a/drm/nouveau/nouveau_abi16.c b/drm/nouveau/nouveau_abi16.c
index 998f5cb2..7f50cf5f 100644
--- a/drm/nouveau/nouveau_abi16.c
+++ b/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/drm/nouveau/nouveau_abi16.h b/drm/nouveau/nouveau_abi16.h
index fa1d856d..841cc556 100644
--- a/drm/nouveau/nouveau_abi16.h
+++ b/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/drm/nouveau/nouveau_usif.c b/drm/nouveau/nouveau_usif.c
index cb1182d7..89dc4ce6 100644
--- a/drm/nouveau/nouveau_usif.c
+++ b/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: