OSDN Git Service

nouveau: support multiple channels per client (breaks drm interface)
authorBen Skeggs <skeggsb@gmail.com>
Wed, 21 Mar 2007 06:57:47 +0000 (17:57 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Wed, 21 Mar 2007 06:57:47 +0000 (17:57 +1100)
shared-core/nouveau_drm.h
shared-core/nouveau_drv.h
shared-core/nouveau_fifo.c
shared-core/nouveau_object.c

index 8a1964e..c3a69a8 100644 (file)
@@ -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;
index c27c93e..92aea31 100644 (file)
@@ -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 */
index 3ffb051..fd5e46a 100644 (file)
@@ -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;i<nouveau_fifo_number(dev);i++)
-               if (dev_priv->fifos[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);
 }
 
 /***********************************
index 83f039d..ace7c2a 100644 (file)
@@ -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);
        }