summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2000-04-17 22:58:40 +0000
committerJeff Hartmann <jhartmann@valinux.com>2000-04-17 22:58:40 +0000
commiteadc29ab406b7deb451cc892abeadd9a626bcea0 (patch)
tree9b9c60e9bf5a8cb3a96526990a2a654e3420542c /linux
parentbacf10aec16ac4245c6f705796670228ee520042 (diff)
Fixed hole where the buffer mappings get copied on fork (requires
2.3.99-pre6 which is not out yet)
Diffstat (limited to 'linux')
-rw-r--r--linux/i810_dma.c77
-rw-r--r--linux/i810_drv.h23
2 files changed, 78 insertions, 22 deletions
diff --git a/linux/i810_dma.c b/linux/i810_dma.c
index ac9eea53..364374e2 100644
--- a/linux/i810_dma.c
+++ b/linux/i810_dma.c
@@ -150,37 +150,99 @@ static struct file_operations i810_buffer_fops = {
poll: drm_poll,
};
+/* These handle currently mapped */
+void drm_i810_vm_open(struct vm_area_struct *vma)
+{
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_buf_t *buf = vma->vm_private_data;
+ drm_i810_buf_priv_t *buf_priv;
+
+ if(!buf) goto out_vm_open;
+ buf_priv = buf->dev_private;
+ if(!buf_priv) goto out_vm_open;
+ buf_priv->map_count++;
+ if(buf_priv->map_count == 1) {
+ buf_priv->currently_mapped = I810_BUF_MAPPED;
+ }
+
+out_vm_open:
+ atomic_inc(&dev->vma_count);
+ MOD_INC_USE_COUNT;
+}
+
+void drm_i810_vm_close(struct vm_area_struct *vma)
+{
+ drm_file_t *priv = vma->vm_file->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_buf_t *buf = vma->vm_private_data;
+ drm_i810_buf_priv_t *buf_priv;
+
+ if(!buf) goto out_vm_close;
+ buf_priv = buf->dev_private;
+ if(!buf_priv) goto out_vm_close;
+ buf_priv->map_count--;
+ if(buf_priv->map_count == 0) {
+ buf_priv->currently_mapped = I810_BUF_UNMAPPED;
+ buf_priv->virtual = 0;
+ }
+
+out_vm_close:
+ MOD_DEC_USE_COUNT;
+ atomic_dec(&dev->vma_count);
+}
+
+struct vm_operations_struct drm_i810_vm_ops = {
+ nopage: drm_vm_nopage,
+ open: drm_i810_vm_open,
+ close: drm_i810_vm_close,
+};
+
int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
{
- vma->vm_flags |= VM_IO;
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
+ drm_i810_private_t *dev_priv = dev->dev_private;
+ drm_buf_t *buf = dev_priv->mmap_buffer;
+
+ vma->vm_flags |= (VM_IO | VM_DONTCOPY);
+ vma->vm_ops = &drm_i810_vm_ops;
+ vma->vm_private_data = buf;
+ vma->vm_file = filp;
+
if (remap_page_range(vma->vm_start,
VM_OFFSET(vma),
vma->vm_end - vma->vm_start,
vma->vm_page_prot)) return -EAGAIN;
+ vma->vm_ops->open(vma);
return 0;
}
static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
{
+ drm_file_t *priv = filp->private_data;
+ drm_device_t *dev = priv->dev;
drm_i810_buf_priv_t *buf_priv = buf->dev_private;
- int retcode = 0;
+ drm_i810_private_t *dev_priv = dev->dev_private;
struct file_operations *old_fops;
+ int retcode = 0;
if(buf_priv->currently_mapped == I810_BUF_MAPPED) return -EINVAL;
down(&current->mm->mmap_sem);
old_fops = filp->f_op;
filp->f_op = &i810_buffer_fops;
+ dev_priv->mmap_buffer = buf;
buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total,
PROT_READ|PROT_WRITE,
MAP_SHARED,
buf->bus_address);
+ dev_priv->mmap_buffer = NULL;
filp->f_op = old_fops;
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;
+ buf_priv->virtual = 0;
}
up(&current->mm->mmap_sem);
return retcode;
@@ -195,8 +257,6 @@ static int i810_unmap_buffer(drm_buf_t *buf)
down(&current->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(&current->mm->mmap_sem);
return retcode;
@@ -205,6 +265,7 @@ static int i810_unmap_buffer(drm_buf_t *buf)
static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
struct file *filp)
{
+ drm_file_t *priv = filp->private_data;
drm_buf_t *buf;
drm_i810_buf_priv_t *buf_priv;
int retcode = 0;
@@ -223,7 +284,7 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
__FUNCTION__, retcode);
goto out_get_buf;
}
- buf->pid = current->pid;
+ buf->pid = priv->pid;
buf_priv = buf->dev_private;
d->granted = 1;
d->request_idx = buf->idx;
@@ -1102,8 +1163,6 @@ void i810_reclaim_buffers(drm_device_t *dev, pid_t pid)
if (used == I810_BUF_CLIENT)
DRM_DEBUG("reclaimed from client\n");
-
- buf_priv->currently_mapped = I810_BUF_UNMAPPED;
}
}
}
diff --git a/linux/i810_drv.h b/linux/i810_drv.h
index 671489d3..38e8a92b 100644
--- a/linux/i810_drv.h
+++ b/linux/i810_drv.h
@@ -32,6 +32,15 @@
#ifndef _I810_DRV_H_
#define _I810_DRV_H_
+typedef struct drm_i810_buf_priv {
+ u32 *in_use;
+ int my_use_idx;
+ int currently_mapped;
+ void *virtual;
+ void *kernel_virtual;
+ int map_count;
+} drm_i810_buf_priv_t;
+
typedef struct _drm_i810_ring_buffer{
int tail_mask;
unsigned long Start;
@@ -55,7 +64,7 @@ typedef struct drm_i810_private {
atomic_t flush_done;
wait_queue_head_t flush_queue; /* Processes waiting until flush */
-
+ drm_buf_t *mmap_buffer;
u32 front_di1, back_di1, zi1;
@@ -129,18 +138,6 @@ extern int i810_rmctx(struct inode *inode, struct file *filp,
extern int i810_context_switch(drm_device_t *dev, int old, int new);
extern int i810_context_switch_complete(drm_device_t *dev, int new);
-
-
-
-typedef struct drm_i810_buf_priv {
- u32 *in_use;
- int my_use_idx;
- int currently_mapped;
- void *virtual;
- void *kernel_virtual;
-} drm_i810_buf_priv_t;
-
-
#define I810_VERBOSE 0