summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-03-21 17:57:47 +1100
committerBen Skeggs <skeggsb@gmail.com>2007-03-21 17:57:47 +1100
commite22225416a12c2beab7a5bcb866d214ee212cbc4 (patch)
tree8c8ec750fed8c21c1b0f8001c6101be4a485967b
parent209870a88262a4a27b36e5cc97f3b1e7021dbefd (diff)
nouveau: support multiple channels per client (breaks drm interface)
-rw-r--r--shared-core/nouveau_drm.h4
-rw-r--r--shared-core/nouveau_drv.h4
-rw-r--r--shared-core/nouveau_fifo.c15
-rw-r--r--shared-core/nouveau_object.c42
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;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);
}
/***********************************
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);
}