summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/nouveau/nouveau_abi16.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_abi16.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c84
1 files changed, 62 insertions, 22 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index d336c2247d6a..7f50cf5f929e 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"
@@ -32,11 +33,10 @@
#include "nouveau_chan.h"
#include "nouveau_abi16.h"
-struct nouveau_abi16 *
-nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
+static struct nouveau_abi16 *
+nouveau_abi16(struct drm_file *file_priv)
{
struct nouveau_cli *cli = nouveau_cli(file_priv);
- mutex_lock(&cli->mutex);
if (!cli->abi16) {
struct nouveau_abi16 *abi16;
cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL);
@@ -51,8 +51,7 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
* device (ie. the one that belongs to the fd it
* opened)
*/
- if (nvif_device_init(&cli->base.object,
- NOUVEAU_ABI16_DEVICE, NV_DEVICE,
+ if (nvif_device_init(&cli->base.object, 0, NV_DEVICE,
&args, sizeof(args),
&abi16->device) == 0)
return cli->abi16;
@@ -60,12 +59,21 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev)
kfree(cli->abi16);
cli->abi16 = NULL;
}
-
- mutex_unlock(&cli->mutex);
}
return cli->abi16;
}
+struct nouveau_abi16 *
+nouveau_abi16_get(struct drm_file *file_priv)
+{
+ struct nouveau_cli *cli = nouveau_cli(file_priv);
+ mutex_lock(&cli->mutex);
+ if (nouveau_abi16(file_priv))
+ return cli->abi16;
+ mutex_unlock(&cli->mutex);
+ return NULL;
+}
+
int
nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret)
{
@@ -133,7 +141,6 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
/* destroy channel object, all children will be killed too */
if (chan->chan) {
- abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff));
nouveau_channel_idle(chan->chan);
nouveau_channel_del(&chan->chan);
}
@@ -238,7 +245,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
struct drm_nouveau_channel_alloc *init = data;
struct nouveau_cli *cli = nouveau_cli(file_priv);
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nvif_device *device;
int ret;
@@ -268,26 +275,21 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
return nouveau_abi16_put(abi16, -EINVAL);
/* allocate "abi16 channel" data and make up a handle for it */
- init->channel = __ffs64(~abi16->handles);
- if (~abi16->handles == 0)
- return nouveau_abi16_put(abi16, -ENOSPC);
-
chan = kzalloc(sizeof(*chan), GFP_KERNEL);
if (!chan)
return nouveau_abi16_put(abi16, -ENOMEM);
INIT_LIST_HEAD(&chan->notifiers);
list_add(&chan->head, &abi16->channels);
- abi16->handles |= (1ULL << init->channel);
/* create channel object and initialise dma and fence management */
- ret = nouveau_channel_new(drm, device,
- NOUVEAU_ABI16_CHAN(init->channel),
- init->fb_ctxdma_handle,
+ ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
init->tt_ctxdma_handle, &chan->chan);
if (ret)
goto done;
+ init->channel = chan->chan->chid;
+
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA)
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
NOUVEAU_GEM_DOMAIN_GART;
@@ -338,7 +340,7 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel)
struct nouveau_abi16_chan *chan;
list_for_each_entry(chan, &abi16->channels, head) {
- if (chan->chan->user.handle == NOUVEAU_ABI16_CHAN(channel))
+ if (chan->chan->chid == channel)
return chan;
}
@@ -346,10 +348,48 @@ 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;
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
if (unlikely(!abi16))
@@ -366,7 +406,7 @@ int
nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_grobj_alloc *init = data;
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
struct nvif_client *client;
@@ -459,7 +499,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_notifierobj_alloc *info = data;
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
struct nvif_device *device = &abi16->device;
@@ -531,7 +571,7 @@ int
nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_gpuobj_free *fini = data;
- struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
+ struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nouveau_abi16_ntfy *ntfy;
int ret = -ENOENT;