diff options
author | Jérôme Glisse <jglisse@redhat.com> | 2017-08-07 21:43:09 -0400 |
---|---|---|
committer | Jérôme Glisse <jglisse@redhat.com> | 2017-08-29 10:35:01 -0400 |
commit | f89339200932c3c06aec8787746e691ef6320094 (patch) | |
tree | 3462ebe1a72dc3896506951d69e735a28a91f43c /drivers/gpu/drm/nouveau | |
parent | f40471939f9a45a04d819881de535ff4afb6085a (diff) |
drm/nouveau/compote: add channel indirect buffer execute ioctl
Channel indirect buffer execution.
Signed-off-by: Jérôme Glisse <jglisse@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/compote/compote-channel.c | 79 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/compote/compote-driver.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/compote/compote.h | 2 |
3 files changed, 71 insertions, 13 deletions
diff --git a/drivers/gpu/drm/nouveau/compote/compote-channel.c b/drivers/gpu/drm/nouveau/compote/compote-channel.c index 9b9b30e999cb..b5a490acf051 100644 --- a/drivers/gpu/drm/nouveau/compote/compote-channel.c +++ b/drivers/gpu/drm/nouveau/compote/compote-channel.c @@ -30,6 +30,7 @@ #include "nouveau_usif.h" #include "nouveau_abi16.h" #include "nouveau_bo.h" +#include "nouveau_dma.h" int compote_channel_new(struct compote_channel **channelp, struct compote_file *cfile) @@ -97,9 +98,29 @@ void compote_channel_ref(struct compote_channel *channel) void compote_channel_unref(struct compote_channel *channel) { - kref_put(&channel->kref, compote_channel_kref_put); + if (channel) + kref_put(&channel->kref, compote_channel_kref_put); } +struct compote_channel *compote_file_channel_find(struct compote_file *cfile, + uint64_t chid) +{ + struct compote_channel *channel; + + down_write(&cfile->rwsem); + list_for_each_entry (channel, &cfile->channels, list) { + if (channel->nvchan->chid == chid) { + compote_channel_ref(channel); + up_write(&cfile->rwsem); + return channel; + } + } + up_write(&cfile->rwsem); + + return NULL; +} + + int compote_ioctl_channel_alloc(struct compote_file *cfile, void __user *uarg) { struct compote_ioctl_channel_alloc arg; @@ -135,17 +156,49 @@ int compote_ioctl_channel_free(struct compote_file *cfile, if (ret) return ret; - down_write(&cfile->rwsem); - list_for_each_entry (channel, &cfile->channels, list) { - if (channel->nvchan->chid == arg.channel) { - compote_channel_ref(channel); - up_write(&cfile->rwsem); - compote_channel_unref(channel); - compote_channel_unref(channel); - return 0; - } - } - up_write(&cfile->rwsem); + channel = compote_file_channel_find(cfile, arg.channel); + compote_channel_unref(channel); + compote_channel_unref(channel); + + return channel ? 0 : -EINVAL; +} + +int compote_ioctl_channel_execute(struct compote_file *cfile, + void __user *uarg) +{ + struct compote_ioctl_channel_execute arg; + struct compote_channel *channel; + struct nouveau_channel *nvchan; + struct nouveau_bo *pb; + int ip, ret; + + ret = copy_from_user(&arg, uarg, sizeof(arg)); + if (ret) + return ret; + + if (arg.ndw > 0x003fffff) + return -EINVAL; + + channel = compote_file_channel_find(cfile, arg.channel); + if (channel == NULL) + return -EINVAL; + nvchan = channel->nvchan; - return -EINVAL; + ret = nouveau_dma_wait(nvchan, 1, 0); + if (ret) + return ret; + + pb = nvchan->push.buffer; + ip = (nvchan->dma.ib_put * 2) + nvchan->dma.ib_base; + nouveau_bo_wr32(pb, ip++, lower_32_bits(arg.addr)); + nouveau_bo_wr32(pb, ip++, upper_32_bits(arg.addr) | arg.ndw << 10); + nvchan->dma.ib_put = (nvchan->dma.ib_put + 1) & nvchan->dma.ib_max; + mb(); + /* Flush writes. */ + nouveau_bo_rd32(pb, 0); + nvif_wr32(&nvchan->user, 0x8c, nvchan->dma.ib_put); + nvchan->dma.ib_free--; + + compote_channel_unref(channel); + return 0; } diff --git a/drivers/gpu/drm/nouveau/compote/compote-driver.c b/drivers/gpu/drm/nouveau/compote/compote-driver.c index 002290d5c9f6..7d58a5de0681 100644 --- a/drivers/gpu/drm/nouveau/compote/compote-driver.c +++ b/drivers/gpu/drm/nouveau/compote/compote-driver.c @@ -226,6 +226,9 @@ static long compote_ioctl(struct file *file, case COMPOTE_IOCTL_CHAN_FREE: ret = compote_ioctl_channel_free(cfile, uarg); break; + case COMPOTE_IOCTL_CHAN_EXEC: + ret = compote_ioctl_channel_execute(cfile, uarg); + break; default: ret = -EINVAL; break; diff --git a/drivers/gpu/drm/nouveau/compote/compote.h b/drivers/gpu/drm/nouveau/compote/compote.h index 0a37d0a1922d..b76d013c4ba7 100644 --- a/drivers/gpu/drm/nouveau/compote/compote.h +++ b/drivers/gpu/drm/nouveau/compote/compote.h @@ -67,6 +67,8 @@ long compote_ioctl_mem_free(struct compote_file *cfile, void __user *uarg); int compote_ioctl_channel_alloc(struct compote_file *cfile, void __user *uarg); int compote_ioctl_channel_free(struct compote_file *cfile, void __user *uarg); +int compote_ioctl_channel_execute(struct compote_file *cfile, + void __user *uarg); void compote_channel_ref(struct compote_channel *channel); void compote_channel_unref(struct compote_channel *channel); |