mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-03 11:40:22 +01:00
Initial checkin of mmap security model
This commit is contained in:
parent
1dcfddf915
commit
136e86822a
12 changed files with 227 additions and 261 deletions
|
|
@ -40,6 +40,9 @@
|
|||
#define I810_BUF_FREE 1
|
||||
#define I810_BUF_USED 0
|
||||
|
||||
#define I810_BUF_UNMAPPED 0
|
||||
#define I810_BUF_MAPPED 1
|
||||
|
||||
#define I810_REG(reg) 2
|
||||
#define I810_BASE(reg) ((unsigned long) \
|
||||
dev->maplist[I810_REG(reg)]->handle)
|
||||
|
|
@ -135,28 +138,87 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
|
||||
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
int i;
|
||||
drm_buf_t *buf;
|
||||
|
||||
for (i = d->granted_count; i < d->request_count; i++) {
|
||||
buf = i810_freelist_get(dev);
|
||||
if (!buf) break;
|
||||
buf->pid = current->pid;
|
||||
copy_to_user_ret(&d->request_indices[i],
|
||||
&buf->idx,
|
||||
sizeof(buf->idx),
|
||||
-EFAULT);
|
||||
copy_to_user_ret(&d->request_sizes[i],
|
||||
&buf->total,
|
||||
sizeof(buf->total),
|
||||
-EFAULT);
|
||||
++d->granted_count;
|
||||
}
|
||||
vma->vm_flags |= VM_IO;
|
||||
if (remap_page_range(vma->vm_start,
|
||||
VM_OFFSET(vma),
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot)) return -EAGAIN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
|
||||
{
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int retcode = 0;
|
||||
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
|
||||
down(¤t->mm->mmap_sem);
|
||||
filp->f_op->mmap = i810_mmap_buffers;
|
||||
buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
buf->bus_address);
|
||||
filp->f_op->mmap = drm_mmap;
|
||||
if ((unsigned long)buf_priv->virtual > -1024UL) {
|
||||
/* Real error */
|
||||
DRM_DEBUG("mmap error\n");
|
||||
retcode = (signed int)buf_priv->virtual;
|
||||
} else {
|
||||
buf_priv->currently_mapped = I810_BUF_MAPPED;
|
||||
}
|
||||
up(¤t->mm->mmap_sem);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_unmap_buffer(drm_buf_t *buf)
|
||||
{
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int retcode = 0;
|
||||
|
||||
if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL;
|
||||
down(¤t->mm->mmap_sem);
|
||||
retcode = do_munmap((unsigned long)buf_priv->virtual,
|
||||
(size_t) buf->total);
|
||||
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
|
||||
buf_priv->virtual = 0;
|
||||
up(¤t->mm->mmap_sem);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
|
||||
struct file *filp)
|
||||
{
|
||||
drm_buf_t *buf;
|
||||
drm_i810_buf_priv_t *buf_priv;
|
||||
int retcode = 0;
|
||||
|
||||
buf = i810_freelist_get(dev);
|
||||
if (!buf) {
|
||||
retcode = -ENOMEM;
|
||||
DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode);
|
||||
goto out_get_buf;
|
||||
}
|
||||
|
||||
retcode = i810_map_buffer(buf, filp);
|
||||
if(retcode) {
|
||||
i810_freelist_put(dev, buf);
|
||||
DRM_DEBUG("mapbuf failed in %s retcode %d\n", __FUNCTION__, retcode);
|
||||
goto out_get_buf;
|
||||
}
|
||||
buf->pid = current->pid;
|
||||
buf_priv = buf->dev_private;
|
||||
d->granted = 1;
|
||||
d->request_idx = buf->idx;
|
||||
d->request_size = buf->total;
|
||||
d->virtual = buf_priv->virtual;
|
||||
|
||||
out_get_buf:
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static unsigned long i810_alloc_page(drm_device_t *dev)
|
||||
{
|
||||
unsigned long address;
|
||||
|
|
@ -395,6 +457,9 @@ static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf,
|
|||
OUT_RING( I810_BUF_FREE );
|
||||
OUT_RING( CMD_REPORT_HEAD );
|
||||
ADVANCE_LP_RING();
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) {
|
||||
i810_unmap_buffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void i810_dma_dispatch_vertex(drm_device_t *dev,
|
||||
|
|
@ -465,6 +530,9 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
|
|||
OUT_RING( CMD_REPORT_HEAD );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_LP_RING();
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) {
|
||||
i810_unmap_buffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -727,6 +795,9 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
|
|||
if (buf->pid == pid && buf_priv) {
|
||||
cmpxchg(buf_priv->in_use,
|
||||
I810_BUF_USED, I810_BUF_FREE);
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) {
|
||||
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -760,19 +831,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
*/
|
||||
|
||||
if (!ret) {
|
||||
#if 0
|
||||
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
|
||||
!= lock.context) {
|
||||
long j = jiffies - dev->lock.lock_time;
|
||||
|
||||
if (j > 0 && j <= DRM_LOCK_SLICE) {
|
||||
/* Can't take lock if we just had it and
|
||||
there is contention. */
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(j);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
for (;;) {
|
||||
if (!dev->lock.hw_lock) {
|
||||
|
|
@ -929,53 +987,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
drm_i810_dma_t d;
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
u32 *hw_status = (u32 *)dev_priv->hw_status_page;
|
||||
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
|
||||
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
DRM_DEBUG("getbuf\n");
|
||||
copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
|
||||
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
|
||||
DRM_ERROR("i810_dma called without lock held\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Please don't send us buffers.
|
||||
*/
|
||||
if (d.send_count != 0) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
|
||||
current->pid, d.send_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We'll send you buffers.
|
||||
*/
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
d.granted = 0;
|
||||
|
||||
if (!retcode && d.request_count) {
|
||||
retcode = i810_dma_get_buffers(dev, &d);
|
||||
}
|
||||
retcode = i810_dma_get_buffer(dev, &d, filp);
|
||||
|
||||
DRM_DEBUG("i810_dma: %d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
|
||||
current->pid, retcode, d.granted);
|
||||
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
sarea_priv->last_dispatch = (int) hw_status[5];
|
||||
|
|
|
|||
|
|
@ -90,4 +90,11 @@ typedef struct _drm_i810_vertex {
|
|||
int discard; /* client is finished with the buffer? */
|
||||
} drm_i810_vertex_t;
|
||||
|
||||
typedef struct drm_i810_dma {
|
||||
void *virtual;
|
||||
int request_idx;
|
||||
int request_size;
|
||||
int granted;
|
||||
} drm_i810_dma_t;
|
||||
|
||||
#endif /* _I810_DRM_H_ */
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { i810_addbufs, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { i810_markbufs, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { i810_infobufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { i810_mapbufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { i810_freebufs, 1, 0 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { i810_addctx, 1, 1 },
|
||||
|
|
@ -93,8 +92,6 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { i810_dma, 1, 0 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { i810_lock, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { i810_unlock, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
|
||||
|
|
@ -107,11 +104,13 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general,1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl,1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 },
|
||||
};
|
||||
|
||||
#define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ extern int i810_unlock(struct inode *inode, struct file *filp,
|
|||
|
||||
/* i810_dma.c */
|
||||
extern int i810_dma_schedule(drm_device_t *dev, int locked);
|
||||
extern int i810_dma(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_getbuf(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_irq_install(drm_device_t *dev, int irq);
|
||||
extern int i810_irq_uninstall(drm_device_t *dev);
|
||||
extern int i810_control(struct inode *inode, struct file *filp,
|
||||
|
|
@ -97,8 +97,6 @@ extern int i810_markbufs(struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_freebufs(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_mapbufs(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_addmap(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
|
|
@ -124,16 +122,13 @@ extern int i810_context_switch_complete(drm_device_t *dev, int new);
|
|||
|
||||
|
||||
|
||||
/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer.
|
||||
* This can be fixed by emitting directly to the ringbuffer in the
|
||||
* 'vertex_dma' ioctl.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct drm_i810_buf_priv {
|
||||
u32 *in_use;
|
||||
int my_use_idx;
|
||||
int currently_mapped;
|
||||
void *virtual;
|
||||
} drm_i810_buf_priv_t;
|
||||
|
||||
|
||||
#define I810_DMA_GENERAL 0
|
||||
#define I810_DMA_VERTEX 1
|
||||
#define I810_DMA_DISCARD 2 /* not used */
|
||||
|
|
|
|||
|
|
@ -348,5 +348,5 @@ typedef struct drm_agp_info {
|
|||
#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
|
||||
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
||||
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
||||
|
||||
#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -332,113 +332,3 @@ int i810_freebufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i810_mapbufs(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int retcode = 0;
|
||||
const int zero = 0;
|
||||
unsigned long virtual;
|
||||
unsigned long address;
|
||||
drm_buf_map_t request;
|
||||
int i;
|
||||
|
||||
if (!dma) return -EINVAL;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
spin_lock(&dev->count_lock);
|
||||
if (atomic_read(&dev->buf_alloc)) {
|
||||
spin_unlock(&dev->count_lock);
|
||||
DRM_DEBUG("Busy\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
++dev->buf_use; /* Can't allocate more after this call */
|
||||
spin_unlock(&dev->count_lock);
|
||||
|
||||
copy_from_user_ret(&request,
|
||||
(drm_buf_map_t *)arg,
|
||||
sizeof(request),
|
||||
-EFAULT);
|
||||
DRM_DEBUG("dma->flags : %lx\n", dma->flags);
|
||||
if (request.count >= dma->buf_count) {
|
||||
if(dma->flags & _DRM_DMA_USE_AGP) {
|
||||
drm_i810_private_t *dev_priv =
|
||||
(drm_i810_private_t *)dev->dev_private;
|
||||
drm_map_t *map = NULL;
|
||||
|
||||
map = dev->maplist[dev_priv->buffer_map_idx];
|
||||
if (!map) {
|
||||
DRM_DEBUG("map is null\n");
|
||||
retcode = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
DRM_DEBUG("map->offset : %lx\n", map->offset);
|
||||
DRM_DEBUG("map->size : %lx\n", map->size);
|
||||
DRM_DEBUG("map->type : %d\n", map->type);
|
||||
DRM_DEBUG("map->flags : %x\n", map->flags);
|
||||
DRM_DEBUG("map->handle : %lx\n", map->handle);
|
||||
DRM_DEBUG("map->mtrr : %d\n", map->mtrr);
|
||||
down(¤t->mm->mmap_sem);
|
||||
virtual = do_mmap(filp, 0, map->size,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
(unsigned long)map->offset);
|
||||
|
||||
up(¤t->mm->mmap_sem);
|
||||
} else {
|
||||
down(¤t->mm->mmap_sem);
|
||||
virtual = do_mmap(filp, 0, dma->byte_count,
|
||||
PROT_READ|PROT_WRITE, MAP_SHARED, 0);
|
||||
up(¤t->mm->mmap_sem);
|
||||
}
|
||||
if (virtual > -1024UL) {
|
||||
/* Real error */
|
||||
DRM_DEBUG("mmap error\n");
|
||||
retcode = (signed long)virtual;
|
||||
goto done;
|
||||
}
|
||||
request.virtual = (void *)virtual;
|
||||
|
||||
for (i = 0; i < dma->buf_count; i++) {
|
||||
if (copy_to_user(&request.list[i].idx,
|
||||
&dma->buflist[i]->idx,
|
||||
sizeof(request.list[0].idx))) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
if (copy_to_user(&request.list[i].total,
|
||||
&dma->buflist[i]->total,
|
||||
sizeof(request.list[0].total))) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
if (copy_to_user(&request.list[i].used,
|
||||
&zero,
|
||||
sizeof(zero))) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
address = virtual + dma->buflist[i]->offset;
|
||||
if (copy_to_user(&request.list[i].address,
|
||||
&address,
|
||||
sizeof(address))) {
|
||||
retcode = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
request.count = dma->buf_count;
|
||||
DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode);
|
||||
|
||||
copy_to_user_ret((drm_buf_map_t *)arg,
|
||||
&request,
|
||||
sizeof(request),
|
||||
-EFAULT);
|
||||
|
||||
DRM_DEBUG("retcode : %d\n", retcode);
|
||||
return retcode;
|
||||
}
|
||||
|
|
|
|||
159
linux/i810_dma.c
159
linux/i810_dma.c
|
|
@ -40,6 +40,9 @@
|
|||
#define I810_BUF_FREE 1
|
||||
#define I810_BUF_USED 0
|
||||
|
||||
#define I810_BUF_UNMAPPED 0
|
||||
#define I810_BUF_MAPPED 1
|
||||
|
||||
#define I810_REG(reg) 2
|
||||
#define I810_BASE(reg) ((unsigned long) \
|
||||
dev->maplist[I810_REG(reg)]->handle)
|
||||
|
|
@ -135,28 +138,87 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i810_dma_get_buffers(drm_device_t *dev, drm_dma_t *d)
|
||||
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
int i;
|
||||
drm_buf_t *buf;
|
||||
|
||||
for (i = d->granted_count; i < d->request_count; i++) {
|
||||
buf = i810_freelist_get(dev);
|
||||
if (!buf) break;
|
||||
buf->pid = current->pid;
|
||||
copy_to_user_ret(&d->request_indices[i],
|
||||
&buf->idx,
|
||||
sizeof(buf->idx),
|
||||
-EFAULT);
|
||||
copy_to_user_ret(&d->request_sizes[i],
|
||||
&buf->total,
|
||||
sizeof(buf->total),
|
||||
-EFAULT);
|
||||
++d->granted_count;
|
||||
}
|
||||
vma->vm_flags |= VM_IO;
|
||||
if (remap_page_range(vma->vm_start,
|
||||
VM_OFFSET(vma),
|
||||
vma->vm_end - vma->vm_start,
|
||||
vma->vm_page_prot)) return -EAGAIN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
|
||||
{
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int retcode = 0;
|
||||
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
|
||||
down(¤t->mm->mmap_sem);
|
||||
filp->f_op->mmap = i810_mmap_buffers;
|
||||
buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
buf->bus_address);
|
||||
filp->f_op->mmap = drm_mmap;
|
||||
if ((unsigned long)buf_priv->virtual > -1024UL) {
|
||||
/* Real error */
|
||||
DRM_DEBUG("mmap error\n");
|
||||
retcode = (signed int)buf_priv->virtual;
|
||||
} else {
|
||||
buf_priv->currently_mapped = I810_BUF_MAPPED;
|
||||
}
|
||||
up(¤t->mm->mmap_sem);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_unmap_buffer(drm_buf_t *buf)
|
||||
{
|
||||
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
|
||||
int retcode = 0;
|
||||
|
||||
if(buf_priv->currently_mapped != I810_BUF_MAPPED) return -EINVAL;
|
||||
down(¤t->mm->mmap_sem);
|
||||
retcode = do_munmap((unsigned long)buf_priv->virtual,
|
||||
(size_t) buf->total);
|
||||
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
|
||||
buf_priv->virtual = 0;
|
||||
up(¤t->mm->mmap_sem);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
|
||||
struct file *filp)
|
||||
{
|
||||
drm_buf_t *buf;
|
||||
drm_i810_buf_priv_t *buf_priv;
|
||||
int retcode = 0;
|
||||
|
||||
buf = i810_freelist_get(dev);
|
||||
if (!buf) {
|
||||
retcode = -ENOMEM;
|
||||
DRM_DEBUG("%s retcode %d\n", __FUNCTION__, retcode);
|
||||
goto out_get_buf;
|
||||
}
|
||||
|
||||
retcode = i810_map_buffer(buf, filp);
|
||||
if(retcode) {
|
||||
i810_freelist_put(dev, buf);
|
||||
DRM_DEBUG("mapbuf failed in %s retcode %d\n", __FUNCTION__, retcode);
|
||||
goto out_get_buf;
|
||||
}
|
||||
buf->pid = current->pid;
|
||||
buf_priv = buf->dev_private;
|
||||
d->granted = 1;
|
||||
d->request_idx = buf->idx;
|
||||
d->request_size = buf->total;
|
||||
d->virtual = buf_priv->virtual;
|
||||
|
||||
out_get_buf:
|
||||
return retcode;
|
||||
}
|
||||
|
||||
static unsigned long i810_alloc_page(drm_device_t *dev)
|
||||
{
|
||||
unsigned long address;
|
||||
|
|
@ -395,6 +457,9 @@ static void i810_dma_dispatch_general(drm_device_t *dev, drm_buf_t *buf,
|
|||
OUT_RING( I810_BUF_FREE );
|
||||
OUT_RING( CMD_REPORT_HEAD );
|
||||
ADVANCE_LP_RING();
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) {
|
||||
i810_unmap_buffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void i810_dma_dispatch_vertex(drm_device_t *dev,
|
||||
|
|
@ -465,6 +530,9 @@ static void i810_dma_dispatch_vertex(drm_device_t *dev,
|
|||
OUT_RING( CMD_REPORT_HEAD );
|
||||
OUT_RING( 0 );
|
||||
ADVANCE_LP_RING();
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) {
|
||||
i810_unmap_buffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -727,6 +795,9 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
|
|||
if (buf->pid == pid && buf_priv) {
|
||||
cmpxchg(buf_priv->in_use,
|
||||
I810_BUF_USED, I810_BUF_FREE);
|
||||
if(buf_priv->currently_mapped == I810_BUF_MAPPED) {
|
||||
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -760,19 +831,6 @@ int i810_lock(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
*/
|
||||
|
||||
if (!ret) {
|
||||
#if 0
|
||||
if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
|
||||
!= lock.context) {
|
||||
long j = jiffies - dev->lock.lock_time;
|
||||
|
||||
if (j > 0 && j <= DRM_LOCK_SLICE) {
|
||||
/* Can't take lock if we just had it and
|
||||
there is contention. */
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule_timeout(j);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
for (;;) {
|
||||
if (!dev->lock.hw_lock) {
|
||||
|
|
@ -929,53 +987,32 @@ int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int i810_dma(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
drm_file_t *priv = filp->private_data;
|
||||
drm_device_t *dev = priv->dev;
|
||||
drm_device_dma_t *dma = dev->dma;
|
||||
int retcode = 0;
|
||||
drm_dma_t d;
|
||||
drm_i810_dma_t d;
|
||||
drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
|
||||
u32 *hw_status = (u32 *)dev_priv->hw_status_page;
|
||||
drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
|
||||
|
||||
copy_from_user_ret(&d, (drm_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
DRM_DEBUG("%d %d: %d send, %d req\n",
|
||||
current->pid, d.context, d.send_count, d.request_count);
|
||||
DRM_DEBUG("getbuf\n");
|
||||
copy_from_user_ret(&d, (drm_i810_dma_t *)arg, sizeof(d), -EFAULT);
|
||||
|
||||
if(!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
|
||||
DRM_ERROR("i810_dma called without lock held\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Please don't send us buffers.
|
||||
*/
|
||||
if (d.send_count != 0) {
|
||||
DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
|
||||
current->pid, d.send_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* We'll send you buffers.
|
||||
*/
|
||||
if (d.request_count < 0 || d.request_count > dma->buf_count) {
|
||||
DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
|
||||
current->pid, d.request_count, dma->buf_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
d.granted_count = 0;
|
||||
d.granted = 0;
|
||||
|
||||
if (!retcode && d.request_count) {
|
||||
retcode = i810_dma_get_buffers(dev, &d);
|
||||
}
|
||||
retcode = i810_dma_get_buffer(dev, &d, filp);
|
||||
|
||||
DRM_DEBUG("i810_dma: %d returning, granted = %d\n",
|
||||
current->pid, d.granted_count);
|
||||
DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n",
|
||||
current->pid, retcode, d.granted);
|
||||
|
||||
copy_to_user_ret((drm_dma_t *)arg, &d, sizeof(d), -EFAULT);
|
||||
sarea_priv->last_dispatch = (int) hw_status[5];
|
||||
|
|
|
|||
|
|
@ -90,4 +90,11 @@ typedef struct _drm_i810_vertex {
|
|||
int discard; /* client is finished with the buffer? */
|
||||
} drm_i810_vertex_t;
|
||||
|
||||
typedef struct drm_i810_dma {
|
||||
void *virtual;
|
||||
int request_idx;
|
||||
int request_size;
|
||||
int granted;
|
||||
} drm_i810_dma_t;
|
||||
|
||||
#endif /* _I810_DRM_H_ */
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = { i810_addbufs, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = { i810_markbufs, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = { i810_infobufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = { i810_mapbufs, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = { i810_freebufs, 1, 0 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = { i810_addctx, 1, 1 },
|
||||
|
|
@ -93,8 +92,6 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = { drm_adddraw, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = { drm_rmdraw, 1, 1 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { i810_dma, 1, 0 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = { i810_lock, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = { i810_unlock, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = { drm_finish, 1, 0 },
|
||||
|
|
@ -107,11 +104,13 @@ static drm_ioctl_desc_t i810_ioctls[] = {
|
|||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = { drm_agp_free, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = { drm_agp_bind, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = { drm_agp_unbind, 1, 1 },
|
||||
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_INIT)] = { i810_dma_init, 1, 1 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_VERTEX)] = { i810_dma_vertex, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_DMA)] = { i810_dma_general,1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_FLUSH)] = { i810_flush_ioctl,1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_GETAGE)] = { i810_getage, 1, 0 },
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_I810_GETBUF)] = { i810_getbuf, 1, 0 },
|
||||
};
|
||||
|
||||
#define I810_IOCTL_COUNT DRM_ARRAY_SIZE(i810_ioctls)
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ extern int i810_unlock(struct inode *inode, struct file *filp,
|
|||
|
||||
/* i810_dma.c */
|
||||
extern int i810_dma_schedule(drm_device_t *dev, int locked);
|
||||
extern int i810_dma(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_getbuf(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_irq_install(drm_device_t *dev, int irq);
|
||||
extern int i810_irq_uninstall(drm_device_t *dev);
|
||||
extern int i810_control(struct inode *inode, struct file *filp,
|
||||
|
|
@ -97,8 +97,6 @@ extern int i810_markbufs(struct inode *inode, struct file *filp,
|
|||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_freebufs(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_mapbufs(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
extern int i810_addmap(struct inode *inode, struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
|
|
@ -124,16 +122,13 @@ extern int i810_context_switch_complete(drm_device_t *dev, int new);
|
|||
|
||||
|
||||
|
||||
/* Copy the outstanding cliprects for every I810_DMA_VERTEX buffer.
|
||||
* This can be fixed by emitting directly to the ringbuffer in the
|
||||
* 'vertex_dma' ioctl.
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct drm_i810_buf_priv {
|
||||
u32 *in_use;
|
||||
int my_use_idx;
|
||||
int currently_mapped;
|
||||
void *virtual;
|
||||
} drm_i810_buf_priv_t;
|
||||
|
||||
|
||||
#define I810_DMA_GENERAL 0
|
||||
#define I810_DMA_VERTEX 1
|
||||
#define I810_DMA_DISCARD 2 /* not used */
|
||||
|
|
|
|||
|
|
@ -348,5 +348,5 @@ typedef struct drm_agp_info {
|
|||
#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
|
||||
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
||||
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
||||
|
||||
#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -348,5 +348,5 @@ typedef struct drm_agp_info {
|
|||
#define DRM_IOCTL_I810_DMA DRM_IOW( 0x42, drm_i810_general_t)
|
||||
#define DRM_IOCTL_I810_FLUSH DRM_IO ( 0x43)
|
||||
#define DRM_IOCTL_I810_GETAGE DRM_IO ( 0x44)
|
||||
|
||||
#define DRM_IOCTL_I810_GETBUF DRM_IOW( 0x45, drm_i810_dma_t)
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue