diff options
author | Jeff Hartmann <jhartmann@valinux.com> | 2000-04-17 22:58:40 +0000 |
---|---|---|
committer | Jeff Hartmann <jhartmann@valinux.com> | 2000-04-17 22:58:40 +0000 |
commit | eadc29ab406b7deb451cc892abeadd9a626bcea0 (patch) | |
tree | 9b9c60e9bf5a8cb3a96526990a2a654e3420542c /linux | |
parent | bacf10aec16ac4245c6f705796670228ee520042 (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.c | 77 | ||||
-rw-r--r-- | linux/i810_drv.h | 23 |
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(¤t->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(¤t->mm->mmap_sem); return retcode; @@ -195,8 +257,6 @@ static int i810_unmap_buffer(drm_buf_t *buf) 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; @@ -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 |