drm/nv50: fix iommu errors caused by device reading from address 0
[safe/jmp/linux-2.6] / drivers / gpu / drm / drm_vm.c
index c234c6f..c3b13fb 100644 (file)
@@ -36,6 +36,7 @@
 #include "drmP.h"
 #if defined(__ia64__)
 #include <linux/efi.h>
+#include <linux/slab.h>
 #endif
 
 static void drm_vm_open(struct vm_area_struct *vma);
@@ -91,7 +92,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
        struct drm_file *priv = vma->vm_file->private_data;
        struct drm_device *dev = priv->minor->dev;
-       struct drm_map *map = NULL;
+       struct drm_local_map *map = NULL;
        struct drm_map_list *r_list;
        struct drm_hash_item *hash;
 
@@ -115,9 +116,9 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                 * Using vm_pgoff as a selector forces us to use this unusual
                 * addressing scheme.
                 */
-               unsigned long offset = (unsigned long)vmf->virtual_address -
-                                                               vma->vm_start;
-               unsigned long baddr = map->offset + offset;
+               resource_size_t offset = (unsigned long)vmf->virtual_address -
+                       vma->vm_start;
+               resource_size_t baddr = map->offset + offset;
                struct drm_agp_mem *agpmem;
                struct page *page;
 
@@ -144,13 +145,15 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                 * Get the page, inc the use count, and return it
                 */
                offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
-               page = virt_to_page(__va(agpmem->memory->memory[offset]));
+               page = agpmem->memory->pages[offset];
                get_page(page);
                vmf->page = page;
 
                DRM_DEBUG
-                   ("baddr = 0x%lx page = 0x%p, offset = 0x%lx, count=%d\n",
-                    baddr, __va(agpmem->memory->memory[offset]), offset,
+                   ("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n",
+                    (unsigned long long)baddr,
+                    agpmem->memory->pages[offset],
+                    (unsigned long long)offset,
                     page_count(page));
                return 0;
        }
@@ -176,7 +179,7 @@ static int drm_do_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
  */
 static int drm_do_vm_shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+       struct drm_local_map *map = vma->vm_private_data;
        unsigned long offset;
        unsigned long i;
        struct page *page;
@@ -209,7 +212,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
        struct drm_file *priv = vma->vm_file->private_data;
        struct drm_device *dev = priv->minor->dev;
        struct drm_vma_entry *pt, *temp;
-       struct drm_map *map;
+       struct drm_local_map *map;
        struct drm_map_list *r_list;
        int found_maps = 0;
 
@@ -225,7 +228,7 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                        found_maps++;
                if (pt->vma == vma) {
                        list_del(&pt->head);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+                       kfree(pt);
                }
        }
 
@@ -267,8 +270,11 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
                                dmah.size = map->size;
                                __drm_pci_free(dev, &dmah);
                                break;
+                       case _DRM_GEM:
+                               DRM_ERROR("tried to rmmap GEM object\n");
+                               break;
                        }
-                       drm_free(map, sizeof(*map), DRM_MEM_MAPS);
+                       kfree(map);
                }
        }
        mutex_unlock(&dev->struct_mutex);
@@ -319,7 +325,7 @@ static int drm_do_vm_dma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
  */
 static int drm_do_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
-       struct drm_map *map = (struct drm_map *) vma->vm_private_data;
+       struct drm_local_map *map = vma->vm_private_data;
        struct drm_file *priv = vma->vm_file->private_data;
        struct drm_device *dev = priv->minor->dev;
        struct drm_sg_mem *entry = dev->sg;
@@ -364,28 +370,28 @@ static int drm_vm_sg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 }
 
 /** AGP virtual memory operations */
-static struct vm_operations_struct drm_vm_ops = {
+static const struct vm_operations_struct drm_vm_ops = {
        .fault = drm_vm_fault,
        .open = drm_vm_open,
        .close = drm_vm_close,
 };
 
 /** Shared virtual memory operations */
-static struct vm_operations_struct drm_vm_shm_ops = {
+static const struct vm_operations_struct drm_vm_shm_ops = {
        .fault = drm_vm_shm_fault,
        .open = drm_vm_open,
        .close = drm_vm_shm_close,
 };
 
 /** DMA virtual memory operations */
-static struct vm_operations_struct drm_vm_dma_ops = {
+static const struct vm_operations_struct drm_vm_dma_ops = {
        .fault = drm_vm_dma_fault,
        .open = drm_vm_open,
        .close = drm_vm_close,
 };
 
 /** Scatter-gather virtual memory operations */
-static struct vm_operations_struct drm_vm_sg_ops = {
+static const struct vm_operations_struct drm_vm_sg_ops = {
        .fault = drm_vm_sg_fault,
        .open = drm_vm_open,
        .close = drm_vm_close,
@@ -399,7 +405,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
  * Create a new drm_vma_entry structure as the \p vma private data entry and
  * add it to drm_device::vmalist.
  */
-static void drm_vm_open_locked(struct vm_area_struct *vma)
+void drm_vm_open_locked(struct vm_area_struct *vma)
 {
        struct drm_file *priv = vma->vm_file->private_data;
        struct drm_device *dev = priv->minor->dev;
@@ -409,7 +415,7 @@ static void drm_vm_open_locked(struct vm_area_struct *vma)
                  vma->vm_start, vma->vm_end - vma->vm_start);
        atomic_inc(&dev->vma_count);
 
-       vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
+       vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
        if (vma_entry) {
                vma_entry->vma = vma;
                vma_entry->pid = current->pid;
@@ -449,7 +455,7 @@ static void drm_vm_close(struct vm_area_struct *vma)
        list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
                if (pt->vma == vma) {
                        list_del(&pt->head);
-                       drm_free(pt, sizeof(*pt), DRM_MEM_VMAS);
+                       kfree(pt);
                        break;
                }
        }
@@ -509,14 +515,14 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
        return 0;
 }
 
-unsigned long drm_core_get_map_ofs(struct drm_map * map)
+resource_size_t drm_core_get_map_ofs(struct drm_local_map * map)
 {
        return map->offset;
 }
 
 EXPORT_SYMBOL(drm_core_get_map_ofs);
 
-unsigned long drm_core_get_reg_ofs(struct drm_device *dev)
+resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
 {
 #ifdef __alpha__
        return dev->hose->dense_mem_base - dev->hose->mem_space->start;
@@ -540,12 +546,12 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
  * according to the mapping type and remaps the pages. Finally sets the file
  * pointer and calls vm_open().
  */
-static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 {
        struct drm_file *priv = filp->private_data;
        struct drm_device *dev = priv->minor->dev;
-       struct drm_map *map = NULL;
-       unsigned long offset = 0;
+       struct drm_local_map *map = NULL;
+       resource_size_t offset = 0;
        struct drm_hash_item *hash;
 
        DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
@@ -620,9 +626,9 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
                                       vma->vm_page_prot))
                        return -EAGAIN;
                DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
-                         " offset = 0x%lx\n",
+                         " offset = 0x%llx\n",
                          map->type,
-                         vma->vm_start, vma->vm_end, map->offset + offset);
+                         vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
                vma->vm_ops = &drm_vm_ops;
                break;
        case _DRM_CONSISTENT: