diff options
author | George Sapountzis <gsap7@yahoo.gr> | 2006-10-24 15:03:04 -0400 |
---|---|---|
committer | airlied <airlied@linux.ie> | 2006-12-06 23:53:31 -0500 |
commit | 3417f33e762bf7d4277031a655e3ad07e73ce0be (patch) | |
tree | 255d4871a0a7affbeab8d35f5b072a70ef064cfd | |
parent | 5c2df2bfb121a77d925dba580f53da08b4020528 (diff) |
drm: add flag for mapping PCI DMA buffers read-only.
Add DRM_PCI_BUFFER_RO flag for mapping PCI DMA buffer read-only. An additional
flag is needed, since PCI DMA buffers do not have an associated map.
Signed-off-by: Dave Airlie <airlied@linux.ie>
-rw-r--r-- | drivers/char/drm/drm.h | 3 | ||||
-rw-r--r-- | drivers/char/drm/drmP.h | 3 | ||||
-rw-r--r-- | drivers/char/drm/drm_bufs.c | 10 | ||||
-rw-r--r-- | drivers/char/drm/drm_vm.c | 16 |
4 files changed, 27 insertions, 5 deletions
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 3f28a1551621..8db9041e306c 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h | |||
@@ -356,7 +356,8 @@ typedef struct drm_buf_desc { | |||
356 | _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ | 356 | _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */ |
357 | _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ | 357 | _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */ |
358 | _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ | 358 | _DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */ |
359 | _DRM_FB_BUFFER = 0x08 /**< Buffer is in frame buffer */ | 359 | _DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */ |
360 | _DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */ | ||
360 | } flags; | 361 | } flags; |
361 | unsigned long agp_start; /**< | 362 | unsigned long agp_start; /**< |
362 | * Start address of where the AGP buffers are | 363 | * Start address of where the AGP buffers are |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 2f18329c5eb8..0bbb04f2390f 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -431,7 +431,8 @@ typedef struct drm_device_dma { | |||
431 | enum { | 431 | enum { |
432 | _DRM_DMA_USE_AGP = 0x01, | 432 | _DRM_DMA_USE_AGP = 0x01, |
433 | _DRM_DMA_USE_SG = 0x02, | 433 | _DRM_DMA_USE_SG = 0x02, |
434 | _DRM_DMA_USE_FB = 0x04 | 434 | _DRM_DMA_USE_FB = 0x04, |
435 | _DRM_DMA_USE_PCI_RO = 0x08 | ||
435 | } flags; | 436 | } flags; |
436 | 437 | ||
437 | } drm_device_dma_t; | 438 | } drm_device_dma_t; |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 6eafff13dab6..9f65f5697ba8 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -887,6 +887,9 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
887 | request->count = entry->buf_count; | 887 | request->count = entry->buf_count; |
888 | request->size = size; | 888 | request->size = size; |
889 | 889 | ||
890 | if (request->flags & _DRM_PCI_BUFFER_RO) | ||
891 | dma->flags = _DRM_DMA_USE_PCI_RO; | ||
892 | |||
890 | atomic_dec(&dev->buf_alloc); | 893 | atomic_dec(&dev->buf_alloc); |
891 | return 0; | 894 | return 0; |
892 | 895 | ||
@@ -1471,9 +1474,10 @@ int drm_freebufs(struct inode *inode, struct file *filp, | |||
1471 | * \param arg pointer to a drm_buf_map structure. | 1474 | * \param arg pointer to a drm_buf_map structure. |
1472 | * \return zero on success or a negative number on failure. | 1475 | * \return zero on success or a negative number on failure. |
1473 | * | 1476 | * |
1474 | * Maps the AGP or SG buffer region with do_mmap(), and copies information | 1477 | * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information |
1475 | * about each buffer into user space. The PCI buffers are already mapped on the | 1478 | * about each buffer into user space. For PCI buffers, it calls do_mmap() with |
1476 | * addbufs_pci() call. | 1479 | * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls |
1480 | * drm_mmap_dma(). | ||
1477 | */ | 1481 | */ |
1478 | int drm_mapbufs(struct inode *inode, struct file *filp, | 1482 | int drm_mapbufs(struct inode *inode, struct file *filp, |
1479 | unsigned int cmd, unsigned long arg) | 1483 | unsigned int cmd, unsigned long arg) |
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index b40ae438f531..74686e9a2d34 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c | |||
@@ -473,6 +473,22 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | |||
473 | } | 473 | } |
474 | unlock_kernel(); | 474 | unlock_kernel(); |
475 | 475 | ||
476 | if (!capable(CAP_SYS_ADMIN) && | ||
477 | (dma->flags & _DRM_DMA_USE_PCI_RO)) { | ||
478 | vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE); | ||
479 | #if defined(__i386__) || defined(__x86_64__) | ||
480 | pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; | ||
481 | #else | ||
482 | /* Ye gads this is ugly. With more thought | ||
483 | we could move this up higher and use | ||
484 | `protection_map' instead. */ | ||
485 | vma->vm_page_prot = | ||
486 | __pgprot(pte_val | ||
487 | (pte_wrprotect | ||
488 | (__pte(pgprot_val(vma->vm_page_prot))))); | ||
489 | #endif | ||
490 | } | ||
491 | |||
476 | vma->vm_ops = &drm_vm_dma_ops; | 492 | vma->vm_ops = &drm_vm_dma_ops; |
477 | 493 | ||
478 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ | 494 | vma->vm_flags |= VM_RESERVED; /* Don't swap */ |