patch-2.4.0-test5 linux/drivers/char/drm/vm.c

Next file: linux/drivers/char/efirtc.c
Previous file: linux/drivers/char/drm/tdfx_drv.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test4/linux/drivers/char/drm/vm.c linux/drivers/char/drm/vm.c
@@ -2,6 +2,7 @@
  * Created: Mon Jan  4 08:58:31 1999 by faith@precisioninsight.com
  *
  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -24,12 +25,14 @@
  * DEALINGS IN THE SOFTWARE.
  * 
  * Authors:
- *    Rickard E. (Rik) Faith <faith@precisioninsight.com>
+ *    Rickard E. (Rik) Faith <faith@valinux.com>
  *
  */
 
 #define __NO_VERSION__
 #include "drmP.h"
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
 
 struct vm_operations_struct   drm_vm_ops = {
 	nopage:	 drm_vm_nopage,
@@ -87,7 +90,7 @@
 
 	offset	 = address - vma->vm_start;
 	page	 = offset >> PAGE_SHIFT;
-	physical = (unsigned long)dev->lock.hw_lock + (offset & (~PAGE_MASK));
+	physical = (unsigned long)dev->lock.hw_lock + offset;
 	atomic_inc(&mem_map[MAP_NR(physical)].count); /* Dec. by kernel */
 
 	DRM_DEBUG("0x%08lx (page %lu) => 0x%08lx\n", address, page, physical);
@@ -190,15 +193,22 @@
 int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	drm_device_dma_t *dma	 = dev->dma;
+	drm_device_t	 *dev;
+	drm_device_dma_t *dma;
 	unsigned long	 length	 = vma->vm_end - vma->vm_start;
 	
+	lock_kernel();
+	dev	 = priv->dev;
+	dma	 = dev->dma;
 	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
 		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
 
 				/* Length must match exact page count */
-	if ((length >> PAGE_SHIFT) != dma->page_count) return -EINVAL;
+	if ((length >> PAGE_SHIFT) != dma->page_count) {
+		unlock_kernel();
+		return -EINVAL;
+	}
+	unlock_kernel();
 
 	vma->vm_ops   = &drm_vm_dma_ops;
 	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
@@ -244,13 +254,26 @@
 				/* Check for valid size. */
 	if (map->size != vma->vm_end - vma->vm_start) return -EINVAL;
 	
+	if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) {
+		vma->vm_flags &= VM_MAYWRITE;
+#if defined(__i386__)
+		pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+#else
+				/* Ye gads this is ugly.  With more thought
+                                   we could move this up higher and use
+                                   `protection_map' instead.  */
+		vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
+			__pte(pgprot_val(vma->vm_page_prot)))));
+#endif
+	}
 
 	switch (map->type) {
 	case _DRM_FRAME_BUFFER:
 	case _DRM_REGISTERS:
+	case _DRM_AGP:
 		if (VM_OFFSET(vma) >= __pa(high_memory)) {
 #if defined(__i386__)
-			if (boot_cpu_data.x86 > 3) {
+			if (boot_cpu_data.x86 > 3 && map->type != _DRM_AGP) {
 				pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
 				pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
 			}
@@ -262,6 +285,10 @@
 				     vma->vm_end - vma->vm_start,
 				     vma->vm_page_prot))
 				return -EAGAIN;
+		DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
+			  " offset = 0x%lx\n",
+			  map->type,
+			  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
 		vma->vm_ops = &drm_vm_ops;
 		break;
 	case _DRM_SHM:
@@ -274,19 +301,7 @@
 		return -EINVAL;	/* This should never happen. */
 	}
 	vma->vm_flags |= VM_LOCKED | VM_SHM; /* Don't swap */
-	if (map->flags & _DRM_READ_ONLY) {
-#if defined(__i386__)
-		pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
-#else
-				/* Ye gads this is ugly.  With more thought
-                                   we could move this up higher and use
-                                   `protection_map' instead.  */
-		vma->vm_page_prot = __pgprot(pte_val(pte_wrprotect(
-			__pte(pgprot_val(vma->vm_page_prot)))));
-#endif
-	}
 
-	
 #if LINUX_VERSION_CODE < 0x020203 /* KERNEL_VERSION(2,2,3) */
 				/* In Linux 2.2.3 and above, this is
 				   handled in do_mmap() in mm/mmap.c. */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)