Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * \file drm_memory.c
0003  * Memory management wrappers for DRM
0004  *
0005  * \author Rickard E. (Rik) Faith <faith@valinux.com>
0006  * \author Gareth Hughes <gareth@valinux.com>
0007  */
0008 
0009 /*
0010  * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
0011  *
0012  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
0013  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
0014  * All Rights Reserved.
0015  *
0016  * Permission is hereby granted, free of charge, to any person obtaining a
0017  * copy of this software and associated documentation files (the "Software"),
0018  * to deal in the Software without restriction, including without limitation
0019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0020  * and/or sell copies of the Software, and to permit persons to whom the
0021  * Software is furnished to do so, subject to the following conditions:
0022  *
0023  * The above copyright notice and this permission notice (including the next
0024  * paragraph) shall be included in all copies or substantial portions of the
0025  * Software.
0026  *
0027  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0028  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0029  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0030  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0031  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0032  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0033  * OTHER DEALINGS IN THE SOFTWARE.
0034  */
0035 
0036 #include <linux/export.h>
0037 #include <linux/highmem.h>
0038 #include <linux/pci.h>
0039 #include <linux/vmalloc.h>
0040 
0041 #include <drm/drm_cache.h>
0042 #include <drm/drm_device.h>
0043 
0044 #include "drm_legacy.h"
0045 
0046 #if IS_ENABLED(CONFIG_AGP)
0047 
0048 #ifdef HAVE_PAGE_AGP
0049 # include <asm/agp.h>
0050 #else
0051 # ifdef __powerpc__
0052 #  define PAGE_AGP  pgprot_noncached_wc(PAGE_KERNEL)
0053 # else
0054 #  define PAGE_AGP  PAGE_KERNEL
0055 # endif
0056 #endif
0057 
0058 static void *agp_remap(unsigned long offset, unsigned long size,
0059                struct drm_device *dev)
0060 {
0061     unsigned long i, num_pages =
0062         PAGE_ALIGN(size) / PAGE_SIZE;
0063     struct drm_agp_mem *agpmem;
0064     struct page **page_map;
0065     struct page **phys_page_map;
0066     void *addr;
0067 
0068     size = PAGE_ALIGN(size);
0069 
0070 #ifdef __alpha__
0071     offset -= dev->hose->mem_space->start;
0072 #endif
0073 
0074     list_for_each_entry(agpmem, &dev->agp->memory, head)
0075         if (agpmem->bound <= offset
0076             && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
0077             (offset + size))
0078             break;
0079     if (&agpmem->head == &dev->agp->memory)
0080         return NULL;
0081 
0082     /*
0083      * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
0084      * the CPU do not get remapped by the GART.  We fix this by using the kernel's
0085      * page-table instead (that's probably faster anyhow...).
0086      */
0087     /* note: use vmalloc() because num_pages could be large... */
0088     page_map = vmalloc(array_size(num_pages, sizeof(struct page *)));
0089     if (!page_map)
0090         return NULL;
0091 
0092     phys_page_map = (agpmem->memory->pages + (offset - agpmem->bound) / PAGE_SIZE);
0093     for (i = 0; i < num_pages; ++i)
0094         page_map[i] = phys_page_map[i];
0095     addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
0096     vfree(page_map);
0097 
0098     return addr;
0099 }
0100 
0101 #else /*  CONFIG_AGP  */
0102 static inline void *agp_remap(unsigned long offset, unsigned long size,
0103                   struct drm_device *dev)
0104 {
0105     return NULL;
0106 }
0107 
0108 #endif /* CONFIG_AGP */
0109 
0110 void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev)
0111 {
0112     if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
0113         map->handle = agp_remap(map->offset, map->size, dev);
0114     else
0115         map->handle = ioremap(map->offset, map->size);
0116 }
0117 EXPORT_SYMBOL(drm_legacy_ioremap);
0118 
0119 void drm_legacy_ioremap_wc(struct drm_local_map *map, struct drm_device *dev)
0120 {
0121     if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
0122         map->handle = agp_remap(map->offset, map->size, dev);
0123     else
0124         map->handle = ioremap_wc(map->offset, map->size);
0125 }
0126 EXPORT_SYMBOL(drm_legacy_ioremap_wc);
0127 
0128 void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev)
0129 {
0130     if (!map->handle || !map->size)
0131         return;
0132 
0133     if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP)
0134         vunmap(map->handle);
0135     else
0136         iounmap(map->handle);
0137 }
0138 EXPORT_SYMBOL(drm_legacy_ioremapfree);