nouveau: support multiple channels per client (breaks drm interface)

main
Ben Skeggs 2007-03-21 17:57:47 +11:00
parent 209870a882
commit e22225416a
4 changed files with 42 additions and 37 deletions

View 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;

View 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 */

View 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);
}
/***********************************

View 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));
//FIXME: check args, only allow trusted objects to be created
if (nouveau_object_handle_find(dev, channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
channel, init.handle);
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);
}
obj = nouveau_object_gr_create(dev, channel, init.class);
//FIXME: check args, only allow trusted objects to be created
if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
init.channel, init.handle);
return DRM_ERR(EINVAL);
}
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_dma_object_check_access(dev, &init))
return DRM_ERR(EPERM);
if (nouveau_object_handle_find(dev, channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
channel, init.handle);
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);
}
obj = nouveau_object_dma_create(dev, channel, init.class,
init.offset, init.size,
init.access, init.target);
if (nouveau_dma_object_check_access(dev, &init))
return DRM_ERR(EPERM);
if (nouveau_object_handle_find(dev, init.channel, init.handle)) {
DRM_ERROR("Channel %d: handle 0x%08x already exists\n",
init.channel, init.handle);
return DRM_ERR(EINVAL);
}
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);
}