Fix for multiple sarea bug + agp built into kernel segfault
authorJeff Hartmann <jhartmann@valinux.com>
Mon, 7 Aug 2000 16:55:10 +0000 (16:55 +0000)
committerJeff Hartmann <jhartmann@valinux.com>
Mon, 7 Aug 2000 16:55:10 +0000 (16:55 +0000)
linux-core/drmP.h
linux/agpsupport.c
linux/drmP.h
linux/vm.c

index 3e5149c..516e9b2 100644 (file)
@@ -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);
index 48a6aa5..7ed234e 100644 (file)
@@ -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,
index 3e5149c..516e9b2 100644 (file)
@@ -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);
index 5ee9e32..b1f0d49 100644 (file)
@@ -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;