From e22225416a12c2beab7a5bcb866d214ee212cbc4 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 21 Mar 2007 17:57:47 +1100 Subject: nouveau: support multiple channels per client (breaks drm interface) --- shared-core/nouveau_drm.h | 4 +++- shared-core/nouveau_drv.h | 4 ++-- shared-core/nouveau_fifo.c | 15 ++++++++------- shared-core/nouveau_object.c | 42 ++++++++++++++++++++++-------------------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index 8a1964ed..c3a69a8f 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -25,7 +25,7 @@ #ifndef __NOUVEAU_DRM_H__ #define __NOUVEAU_DRM_H__ -#define NOUVEAU_DRM_HEADER_PATCHLEVEL 4 +#define NOUVEAU_DRM_HEADER_PATCHLEVEL 5 typedef struct drm_nouveau_fifo_alloc { int channel; @@ -40,6 +40,7 @@ typedef struct drm_nouveau_fifo_alloc { drm_nouveau_fifo_alloc_t; typedef struct drm_nouveau_object_init { + int channel; uint32_t handle; int class; } @@ -49,6 +50,7 @@ drm_nouveau_object_init_t; #define NOUVEAU_MEM_ACCESS_WO 2 #define NOUVEAU_MEM_ACCESS_RW 3 typedef struct drm_nouveau_dma_object_init { + int channel; uint32_t handle; int class; int access; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index c27c93ea..92aea31c 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -34,7 +34,7 @@ #define DRIVER_MAJOR 0 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 4 +#define DRIVER_PATCHLEVEL 5 #define NOUVEAU_FAMILY 0x0000FFFF #define NOUVEAU_FLAGS 0xFFFF0000 @@ -187,7 +187,7 @@ extern void nouveau_instmem_w32(drm_nouveau_private_t *dev_priv, extern int nouveau_fifo_init(drm_device_t *dev); extern int nouveau_fifo_number(drm_device_t *dev); extern void nouveau_fifo_cleanup(drm_device_t *dev, DRMFILE filp); -extern int nouveau_fifo_id_get(drm_device_t *dev, DRMFILE filp); +extern int nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel); extern void nouveau_fifo_free(drm_device_t *dev, int channel); /* nouveau_object.c */ diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 3ffb0516..fd5e46ac 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -725,15 +725,16 @@ void nouveau_fifo_cleanup(drm_device_t* dev, DRMFILE filp) nouveau_fifo_init(dev);*/ } -int nouveau_fifo_id_get(drm_device_t* dev, DRMFILE filp) +int +nouveau_fifo_owner(drm_device_t *dev, DRMFILE filp, int channel) { - drm_nouveau_private_t *dev_priv=dev->dev_private; - int i; + drm_nouveau_private_t *dev_priv = dev->dev_private; - for(i=0;ififos[i].used && dev_priv->fifos[i].filp == filp) - return i; - return -1; + if (channel >= nouveau_fifo_number(dev)) + return 0; + if (dev_priv->fifos[channel].used == 0) + return 0; + return (dev_priv->fifos[channel].filp == filp); } /*********************************** diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 83f039db..ace7c2aa 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -475,28 +475,29 @@ int nouveau_ioctl_object_init(DRM_IOCTL_ARGS) DRM_DEVICE; drm_nouveau_object_init_t init; struct nouveau_object *obj; - int channel; - - channel = nouveau_fifo_id_get(dev, filp); - if (channel == -1) - return DRM_ERR(EINVAL); DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_object_init_t __user *) data, sizeof(init)); + if (!nouveau_fifo_owner(dev, filp, init.channel)) { + DRM_ERROR("pid %d doesn't own channel %d\n", + DRM_CURRENTPID, init.channel); + return DRM_ERR(EINVAL); + } + //FIXME: check args, only allow trusted objects to be created - if (nouveau_object_handle_find(dev, channel, init.handle)) { + if (nouveau_object_handle_find(dev, init.channel, init.handle)) { DRM_ERROR("Channel %d: handle 0x%08x already exists\n", - channel, init.handle); + init.channel, init.handle); return DRM_ERR(EINVAL); } - obj = nouveau_object_gr_create(dev, channel, init.class); + obj = nouveau_object_gr_create(dev, init.channel, init.class); if (!obj) return DRM_ERR(ENOMEM); - if (nouveau_ht_object_insert(dev, channel, init.handle, obj)) { + if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) { nouveau_object_free(dev, obj); return DRM_ERR(ENOMEM); } @@ -567,32 +568,33 @@ int nouveau_ioctl_dma_object_init(DRM_IOCTL_ARGS) DRM_DEVICE; drm_nouveau_dma_object_init_t init; struct nouveau_object *obj; - int channel; - - channel = nouveau_fifo_id_get(dev, filp); - if (channel == -1) - return DRM_ERR(EINVAL); DRM_COPY_FROM_USER_IOCTL(init, (drm_nouveau_dma_object_init_t __user *) data, sizeof(init)); + if (!nouveau_fifo_owner(dev, filp, init.channel)) { + DRM_ERROR("pid %d doesn't own channel %d\n", + DRM_CURRENTPID, init.channel); + return DRM_ERR(EINVAL); + } + if (nouveau_dma_object_check_access(dev, &init)) return DRM_ERR(EPERM); - if (nouveau_object_handle_find(dev, channel, init.handle)) { + if (nouveau_object_handle_find(dev, init.channel, init.handle)) { DRM_ERROR("Channel %d: handle 0x%08x already exists\n", - channel, init.handle); + init.channel, init.handle); return DRM_ERR(EINVAL); } - obj = nouveau_object_dma_create(dev, channel, init.class, - init.offset, init.size, - init.access, init.target); + obj = nouveau_object_dma_create(dev, init.channel, init.class, + init.offset, init.size, + init.access, init.target); if (!obj) return DRM_ERR(ENOMEM); obj->handle = init.handle; - if (nouveau_ht_object_insert(dev, channel, init.handle, obj)) { + if (nouveau_ht_object_insert(dev, init.channel, init.handle, obj)) { nouveau_object_free(dev, obj); return DRM_ERR(ENOMEM); } -- cgit v1.2.3