summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Hartmann <jhartmann@valinux.com>2000-08-07 16:55:10 +0000
committerJeff Hartmann <jhartmann@valinux.com>2000-08-07 16:55:10 +0000
commit9199075a6a975ebcc44aff53fe0f77080c01a30b (patch)
tree8d751731b648043da816d48cce133b2964849fce
parentf3ae6786f89a4f63dbba93c5519d3792a1744dd7 (diff)
downloaddrm-9199075a6a975ebcc44aff53fe0f77080c01a30b.tar.gz
Fix for multiple sarea bug + agp built into kernel segfault
-rw-r--r--linux-core/drmP.h6
-rw-r--r--linux/agpsupport.c47
-rw-r--r--linux/drmP.h6
-rw-r--r--linux/vm.c52
4 files changed, 95 insertions, 16 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 3e5149c9..516e9b22 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -558,6 +558,9 @@ extern unsigned long drm_vm_nopage(struct vm_area_struct *vma,
extern unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
+extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access);
extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
@@ -569,6 +572,9 @@ extern struct page *drm_vm_nopage(struct vm_area_struct *vma,
extern struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
+extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access);
extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
diff --git a/linux/agpsupport.c b/linux/agpsupport.c
index 48a6aa5f..7ed234e1 100644
--- a/linux/agpsupport.c
+++ b/linux/agpsupport.c
@@ -287,23 +287,40 @@ drm_agp_head_t *drm_agp_init(void)
return NULL;
memset((void *)head, 0, sizeof(*head));
(*drm_agp.copy_info)(&head->agp_info);
+ if (head->agp_info.chipset == NOT_SUPPORTED) {
+ drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+ return NULL;
+ }
head->memory = NULL;
switch (head->agp_info.chipset) {
- case INTEL_GENERIC: head->chipset = "Intel"; break;
- case INTEL_LX: head->chipset = "Intel 440LX"; break;
- case INTEL_BX: head->chipset = "Intel 440BX"; break;
- case INTEL_GX: head->chipset = "Intel 440GX"; break;
- case INTEL_I810: head->chipset = "Intel i810"; break;
- case VIA_GENERIC: head->chipset = "VIA"; break;
- case VIA_VP3: head->chipset = "VIA VP3"; break;
- case VIA_MVP3: head->chipset = "VIA MVP3"; break;
- case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro"; break;
- case SIS_GENERIC: head->chipset = "SiS"; break;
- case AMD_GENERIC: head->chipset = "AMD"; break;
- case AMD_IRONGATE: head->chipset = "AMD Irongate"; break;
- case ALI_GENERIC: head->chipset = "ALi"; break;
- case ALI_M1541: head->chipset = "ALi M1541"; break;
- default:
+ case INTEL_GENERIC: head->chipset = "Intel"; break;
+ case INTEL_LX: head->chipset = "Intel 440LX"; break;
+ case INTEL_BX: head->chipset = "Intel 440BX"; break;
+ case INTEL_GX: head->chipset = "Intel 440GX"; break;
+ case INTEL_I810: head->chipset = "Intel i810"; break;
+
+#if LINUX_VERSION_CODE >= 0x020400
+ case INTEL_I840: head->chipset = "Intel i840"; break;
+#endif
+
+ case VIA_GENERIC: head->chipset = "VIA"; break;
+ case VIA_VP3: head->chipset = "VIA VP3"; break;
+ case VIA_MVP3: head->chipset = "VIA MVP3"; break;
+
+#if LINUX_VERSION_CODE >= 0x020400
+ case VIA_MVP4: head->chipset = "VIA MVP4"; break;
+ case VIA_APOLLO_SUPER: head->chipset = "VIA Apollo Super";
+ break;
+#endif
+
+ case VIA_APOLLO_PRO: head->chipset = "VIA Apollo Pro";
+ break;
+ case SIS_GENERIC: head->chipset = "SiS"; break;
+ case AMD_GENERIC: head->chipset = "AMD"; break;
+ case AMD_IRONGATE: head->chipset = "AMD Irongate"; break;
+ case ALI_GENERIC: head->chipset = "ALi"; break;
+ case ALI_M1541: head->chipset = "ALi M1541"; break;
+ default: head->chipset = "Unknown"; break;
}
DRM_INFO("AGP %d.%d on %s @ 0x%08lx %dMB\n",
head->agp_info.version.major,
diff --git a/linux/drmP.h b/linux/drmP.h
index 3e5149c9..516e9b22 100644
--- a/linux/drmP.h
+++ b/linux/drmP.h
@@ -558,6 +558,9 @@ extern unsigned long drm_vm_nopage(struct vm_area_struct *vma,
extern unsigned long drm_vm_shm_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
+extern unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access);
extern unsigned long drm_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
@@ -569,6 +572,9 @@ extern struct page *drm_vm_nopage(struct vm_area_struct *vma,
extern struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
+extern struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access);
extern struct page *drm_vm_dma_nopage(struct vm_area_struct *vma,
unsigned long address,
int write_access);
diff --git a/linux/vm.c b/linux/vm.c
index 5ee9e324..b1f0d49a 100644
--- a/linux/vm.c
+++ b/linux/vm.c
@@ -44,6 +44,12 @@ struct vm_operations_struct drm_vm_shm_ops = {
close: drm_vm_close,
};
+struct vm_operations_struct drm_vm_shm_lock_ops = {
+ nopage: drm_vm_shm_nopage_lock,
+ open: drm_vm_open,
+ close: drm_vm_close,
+};
+
struct vm_operations_struct drm_vm_dma_ops = {
nopage: drm_vm_dma_nopage,
open: drm_vm_open,
@@ -77,6 +83,40 @@ struct page *drm_vm_shm_nopage(struct vm_area_struct *vma,
int write_access)
#endif
{
+#if LINUX_VERSION_CODE >= 0x020300
+ drm_map_t *map = (drm_map_t *)vma->vm_private_data;
+#else
+ drm_map_t *map = (drm_map_t *)vma->vm_pte;
+#endif
+ unsigned long physical;
+ unsigned long offset;
+
+ if (address > vma->vm_end) return NOPAGE_SIGBUS; /* Disallow mremap */
+ if (!map) return NOPAGE_OOM; /* Nothing allocated */
+
+ offset = address - vma->vm_start;
+ physical = (unsigned long)map->handle + offset;
+ atomic_inc(&mem_map[MAP_NR(physical)].count); /* Dec. by kernel */
+
+ DRM_DEBUG("0x%08lx => 0x%08lx\n", address, physical);
+#if LINUX_VERSION_CODE < 0x020317
+ return physical;
+#else
+ return mem_map + MAP_NR(physical);
+#endif
+}
+
+#if LINUX_VERSION_CODE < 0x020317
+unsigned long drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access)
+#else
+ /* Return type changed in 2.3.23 */
+struct page *drm_vm_shm_nopage_lock(struct vm_area_struct *vma,
+ unsigned long address,
+ int write_access)
+#endif
+{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->dev;
unsigned long physical;
@@ -298,7 +338,17 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_SHM:
- vma->vm_ops = &drm_vm_shm_ops;
+ if (map->flags & _DRM_CONTAINS_LOCK)
+ vma->vm_ops = &drm_vm_shm_lock_ops;
+ else {
+ vma->vm_ops = &drm_vm_shm_ops;
+#if LINUX_VERSION_CODE >= 0x020300
+ vma->vm_private_data = (void *)map;
+#else
+ vma->vm_pte = (unsigned long)map;
+#endif
+ }
+
/* Don't let this area swap. Change when
DRM_KERNEL advisory is supported. */
vma->vm_flags |= VM_LOCKED;