Release 4.11 drivers/gpu/drm/drm_vm.c
/**
* \file drm_vm.c
* Memory mapping for DRM
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
* \author Gareth Hughes <gareth@valinux.com>
*/
/*
* Created: Mon Jan 4 08:58:31 1999 by faith@valinux.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
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <drm/drmP.h>
#include <linux/export.h>
#include <linux/seq_file.h>
#if defined(__ia64__)
#include <linux/efi.h>
#include <linux/slab.h>
#endif
#include <asm/pgtable.h>
#include "drm_internal.h"
#include "drm_legacy.h"
struct drm_vma_entry {
struct list_head head;
struct vm_area_struct *vma;
pid_t pid;
};
static void drm_vm_open(struct vm_area_struct *vma);
static void drm_vm_close(struct vm_area_struct *vma);
static pgprot_t drm_io_prot(struct drm_local_map *map,
struct vm_area_struct *vma)
{
pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
tmp = pgprot_noncached(tmp);
else
tmp = pgprot_writecombine(tmp);
#elif defined(__ia64__)
if (efi_range_is_wc(vma->vm_start, vma->vm_end -
vma->vm_start))
tmp = pgprot_writecombine(tmp);
else
tmp = pgprot_noncached(tmp);
#elif defined(__sparc__) || defined(__arm__) || defined(__mips__)
tmp = pgprot_noncached(tmp);
#endif
return tmp;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Airlie | 79 | 56.43% | 1 | 12.50% |
Andrew Lutomirski | 26 | 18.57% | 2 | 25.00% |
Benjamin Herrenschmidt | 24 | 17.14% | 2 | 25.00% |
Huacai Chen | 5 | 3.57% | 1 | 12.50% |
Jordan Crouse | 5 | 3.57% | 1 | 12.50% |
Adrian Bunk | 1 | 0.71% | 1 | 12.50% |
Total | 140 | 100.00% | 8 | 100.00% |
static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
{
pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
tmp = pgprot_noncached_wc(tmp);
#endif
return tmp;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Benjamin Herrenschmidt | 41 | 87.23% | 2 | 66.67% |
Dave Airlie | 6 | 12.77% | 1 | 33.33% |
Total | 47 | 100.00% | 3 | 100.00% |
/**
* \c fault method for AGP virtual memory.
*
* \param vma virtual memory area.
* \param address access address.
* \return pointer to the page structure.
*
* Find the right map and if it's AGP memory find the real physical page to
* map, get the page, increment the use count and return it.
*/
#if IS_ENABLED(CONFIG_AGP)
static int drm_vm_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev;
struct drm_local_map *map = NULL;
struct drm_map_list *r_list;
struct drm_hash_item *hash;
/*
* Find the right map
*/
if (!dev->agp)
goto vm_fault_error;
if (!dev->agp || !dev->agp->cant_use_aperture)
goto vm_fault_error;
if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash))
goto vm_fault_error;
r_list = drm_hash_entry(hash, struct drm_map_list, hash);
map = r_list->map;
if (map && map->type == _DRM_AGP) {
/*
* Using vm_pgoff as a selector forces us to use this unusual
* addressing scheme.
*/
resource_size_t offset = vmf->address - vma->vm_start;
resource_size_t baddr = map->offset + offset;
struct drm_agp_mem *agpmem;
struct page *page;
#ifdef __alpha__
/*
* Adjust to a bus-relative address
*/
baddr -= dev->hose->mem_space->start;
#endif
/*
* It's AGP memory - find the real physical page to map
*/
list_for_each_entry(agpmem, &dev->agp->memory, head) {
if (agpmem->bound <= baddr &&
agpmem->bound + agpmem->pages * PAGE_SIZE > baddr)
break;
}
if (&agpmem->head == &dev->agp->memory)
goto vm_fault_error;
/*
* Get the page, inc the use count, and return it
*/
offset = (baddr - agpmem->bound) >> PAGE_SHIFT;
page = agpmem->memory->pages[offset];
get_page(page);
vmf->page = page;
DRM_DEBUG
("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;
}
vm_fault_error:
return VM_FAULT_SIGBUS; /* Disallow mremap */
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 153 | 49.35% | 4 | 14.81% |
Dave Airlie | 51 | 16.45% | 11 | 40.74% |
Nicholas Piggin | 43 | 13.87% | 1 | 3.70% |
Thomas Hellstrom | 20 | 6.45% | 1 | 3.70% |
Benjamin Herrenschmidt | 14 | 4.52% | 2 | 7.41% |
Dan Carpenter | 10 | 3.23% | 1 | 3.70% |
Dave Jiang | 9 | 2.90% | 1 | 3.70% |
Linus Torvalds (pre-git) | 3 | 0.97% | 1 | 3.70% |
Al Viro | 2 | 0.65% | 1 | 3.70% |
Daniel Vetter | 2 | 0.65% | 1 | 3.70% |
Andrew Morton | 1 | 0.32% | 1 | 3.70% |
Jan Kara | 1 | 0.32% | 1 | 3.70% |
Ross Zwisler | 1 | 0.32% | 1 | 3.70% |
Total | 310 | 100.00% | 27 | 100.00% |
#else
static int drm_vm_fault(struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Nicholas Piggin | 6 | 42.86% | 1 | 20.00% |
Linus Torvalds | 3 | 21.43% | 1 | 20.00% |
Dave Airlie | 3 | 21.43% | 1 | 20.00% |
Linus Torvalds (pre-git) | 1 | 7.14% | 1 | 20.00% |
Ross Zwisler | 1 | 7.14% | 1 | 20.00% |
Total | 14 | 100.00% | 5 | 100.00% |
#endif
/**
* \c nopage method for shared virtual memory.
*
* \param vma virtual memory area.
* \param address access address.
* \return pointer to the page structure.
*
* Get the mapping, find the real physical page to map, get the page, and
* return it.
*/
static int drm_vm_shm_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_local_map *map = vma->vm_private_data;
unsigned long offset;
unsigned long i;
struct page *page;
if (!map)
return VM_FAULT_SIGBUS; /* Nothing allocated */
offset = vmf->address - vma->vm_start;
i = (unsigned long)map->handle + offset;
page = vmalloc_to_page((void *)i);
if (!page)
return VM_FAULT_SIGBUS;
get_page(page);
vmf->page = page;
DRM_DEBUG("shm_fault 0x%lx\n", offset);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 51 | 45.13% | 2 | 18.18% |
Nicholas Piggin | 31 | 27.43% | 1 | 9.09% |
Ingo Molnar | 11 | 9.73% | 2 | 18.18% |
Dave Jiang | 9 | 7.96% | 1 | 9.09% |
Linus Torvalds (pre-git) | 7 | 6.19% | 1 | 9.09% |
Jan Kara | 1 | 0.88% | 1 | 9.09% |
Benjamin Herrenschmidt | 1 | 0.88% | 1 | 9.09% |
Dave Airlie | 1 | 0.88% | 1 | 9.09% |
Ross Zwisler | 1 | 0.88% | 1 | 9.09% |
Total | 113 | 100.00% | 11 | 100.00% |
/**
* \c close method for shared virtual memory.
*
* \param vma virtual memory area.
*
* Deletes map information if we are the last
* person to close a mapping and it's not in the global maplist.
*/
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_local_map *map;
struct drm_map_list *r_list;
int found_maps = 0;
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
map = vma->vm_private_data;
mutex_lock(&dev->struct_mutex);
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma->vm_private_data == map)
found_maps++;
if (pt->vma == vma) {
list_del(&pt->head);
kfree(pt);
}
}
/* We were the only map that was found */
if (found_maps == 1 && map->flags & _DRM_REMOVABLE) {
/* Check to see if we are in the maplist, if we are not, then
* we delete this mappings information.
*/
found_maps = 0;
list_for_each_entry(r_list, &dev->maplist, head) {
if (r_list->map == map)
found_maps++;
}
if (!found_maps) {
drm_dma_handle_t dmah;
switch (map->type) {
case _DRM_REGISTERS:
case _DRM_FRAME_BUFFER:
arch_phys_wc_del(map->mtrr);
iounmap(map->handle);
break;
case _DRM_SHM:
vfree(map->handle);
break;
case _DRM_AGP:
case _DRM_SCATTER_GATHER:
break;
case _DRM_CONSISTENT:
dmah.vaddr = map->handle;
dmah.busaddr = map->offset;
dmah.size = map->size;
__drm_legacy_pci_free(dev, &dmah);
break;
}
kfree(map);
}
}
mutex_unlock(&dev->struct_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 172 | 60.99% | 2 | 9.52% |
Dave Airlie | 85 | 30.14% | 12 | 57.14% |
Linus Torvalds (pre-git) | 18 | 6.38% | 1 | 4.76% |
Eric Anholt | 2 | 0.71% | 1 | 4.76% |
Andrew Lutomirski | 1 | 0.35% | 1 | 4.76% |
Nicholas Piggin | 1 | 0.35% | 1 | 4.76% |
Christoph Hellwig | 1 | 0.35% | 1 | 4.76% |
Benjamin Herrenschmidt | 1 | 0.35% | 1 | 4.76% |
Daniel Vetter | 1 | 0.35% | 1 | 4.76% |
Total | 282 | 100.00% | 21 | 100.00% |
/**
* \c fault method for DMA virtual memory.
*
* \param address access address.
* \return pointer to the page structure.
*
* Determine the page number from the page offset and get it from drm_device_dma::pagelist.
*/
static int drm_vm_dma_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev;
struct drm_device_dma *dma = dev->dma;
unsigned long offset;
unsigned long page_nr;
struct page *page;
if (!dma)
return VM_FAULT_SIGBUS; /* Error */
if (!dma->pagelist)
return VM_FAULT_SIGBUS; /* Nothing allocated */
offset = vmf->address - vma->vm_start;
/* vm_[pg]off[set] should be 0 */
page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */
page = virt_to_page((void *)dma->pagelist[page_nr]);
get_page(page);
vmf->page = page;
DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 52 | 36.88% | 1 | 7.69% |
Nicholas Piggin | 40 | 28.37% | 1 | 7.69% |
Linus Torvalds | 28 | 19.86% | 2 | 15.38% |
Dave Jiang | 9 | 6.38% | 1 | 7.69% |
Dave Airlie | 6 | 4.26% | 5 | 38.46% |
Ben Hutchings | 4 | 2.84% | 1 | 7.69% |
Ross Zwisler | 1 | 0.71% | 1 | 7.69% |
Jan Kara | 1 | 0.71% | 1 | 7.69% |
Total | 141 | 100.00% | 13 | 100.00% |
/**
* \c fault method for scatter-gather virtual memory.
*
* \param address access address.
* \return pointer to the page structure.
*
* Determine the map offset from the page offset and get it from drm_sg_mem::pagelist.
*/
static int drm_vm_sg_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
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;
unsigned long offset;
unsigned long map_offset;
unsigned long page_offset;
struct page *page;
if (!entry)
return VM_FAULT_SIGBUS; /* Error */
if (!entry->pagelist)
return VM_FAULT_SIGBUS; /* Nothing allocated */
offset = vmf->address - vma->vm_start;
map_offset = map->offset - (unsigned long)dev->sg->virtual;
page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
page = entry->pagelist[page_offset];
get_page(page);
vmf->page = page;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 69 | 43.12% | 1 | 6.25% |
Linus Torvalds | 46 | 28.75% | 3 | 18.75% |
Dave Airlie | 17 | 10.62% | 7 | 43.75% |
Nicholas Piggin | 16 | 10.00% | 1 | 6.25% |
Dave Jiang | 9 | 5.62% | 1 | 6.25% |
Jan Kara | 1 | 0.62% | 1 | 6.25% |
Benjamin Herrenschmidt | 1 | 0.62% | 1 | 6.25% |
Ross Zwisler | 1 | 0.62% | 1 | 6.25% |
Total | 160 | 100.00% | 16 | 100.00% |
/** AGP virtual memory operations */
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 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 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 const struct vm_operations_struct drm_vm_sg_ops = {
.fault = drm_vm_sg_fault,
.open = drm_vm_open,
.close = drm_vm_close,
};
static void drm_vm_open_locked(struct drm_device *dev,
struct vm_area_struct *vma)
{
struct drm_vma_entry *vma_entry;
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL);
if (vma_entry) {
vma_entry->vma = vma;
vma_entry->pid = current->pid;
list_add(&vma_entry->head, &dev->vmalist);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 62 | 73.81% | 1 | 12.50% |
Dave Airlie | 11 | 13.10% | 3 | 37.50% |
Rob Clark | 5 | 5.95% | 1 | 12.50% |
Thomas Hellstrom | 3 | 3.57% | 1 | 12.50% |
Eric Anholt | 2 | 2.38% | 1 | 12.50% |
Daniel Vetter | 1 | 1.19% | 1 | 12.50% |
Total | 84 | 100.00% | 8 | 100.00% |
static void drm_vm_open(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev;
mutex_lock(&dev->struct_mutex);
drm_vm_open_locked(dev, vma);
mutex_unlock(&dev->struct_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 40 | 71.43% | 1 | 16.67% |
Linus Torvalds (pre-git) | 7 | 12.50% | 1 | 16.67% |
Dave Airlie | 7 | 12.50% | 3 | 50.00% |
Rob Clark | 2 | 3.57% | 1 | 16.67% |
Total | 56 | 100.00% | 6 | 100.00% |
static void drm_vm_close_locked(struct drm_device *dev,
struct vm_area_struct *vma)
{
struct drm_vma_entry *pt, *temp;
DRM_DEBUG("0x%08lx,0x%08lx\n",
vma->vm_start, vma->vm_end - vma->vm_start);
list_for_each_entry_safe(pt, temp, &dev->vmalist, head) {
if (pt->vma == vma) {
list_del(&pt->head);
kfree(pt);
break;
}
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 50 | 64.94% | 1 | 12.50% |
Dave Airlie | 18 | 23.38% | 3 | 37.50% |
Rob Clark | 5 | 6.49% | 1 | 12.50% |
Chris Wilson | 2 | 2.60% | 1 | 12.50% |
Daniel Vetter | 1 | 1.30% | 1 | 12.50% |
Eric Anholt | 1 | 1.30% | 1 | 12.50% |
Total | 77 | 100.00% | 8 | 100.00% |
/**
* \c close method for all virtual memory types.
*
* \param vma virtual memory area.
*
* Search the \p vma private data entry in drm_device::vmalist, unlink it, and
* free it.
*/
static void drm_vm_close(struct vm_area_struct *vma)
{
struct drm_file *priv = vma->vm_file->private_data;
struct drm_device *dev = priv->minor->dev;
mutex_lock(&dev->struct_mutex);
drm_vm_close_locked(dev, vma);
mutex_unlock(&dev->struct_mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Chris Wilson | 45 | 80.36% | 1 | 25.00% |
Linus Torvalds (pre-git) | 7 | 12.50% | 1 | 25.00% |
Dave Airlie | 2 | 3.57% | 1 | 25.00% |
Rob Clark | 2 | 3.57% | 1 | 25.00% |
Total | 56 | 100.00% | 4 | 100.00% |
/**
* mmap DMA memory.
*
* \param file_priv DRM file private.
* \param vma virtual memory area.
* \return zero on success or a negative number on failure.
*
* Sets the virtual memory area operations structure to vm_dma_ops, the file
* pointer, and calls vm_open().
*/
static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev;
struct drm_device_dma *dma;
unsigned long length = vma->vm_end - vma->vm_start;
dev = priv->minor->dev;
dma = dev->dma;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
vma->vm_start, vma->vm_end, vma->vm_pgoff);
/* Length must match exact page count */
if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
return -EINVAL;
}
if (!capable(CAP_SYS_ADMIN) &&
(dma->flags & _DRM_DMA_USE_PCI_RO)) {
vma->vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
#if defined(__i386__) || defined(__x86_64__)
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
}
vma->vm_ops = &drm_vm_dma_ops;
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
drm_vm_open_locked(dev, vma);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 98 | 48.28% | 3 | 17.65% |
George Sapountzis | 78 | 38.42% | 1 | 5.88% |
Dave Airlie | 16 | 7.88% | 7 | 41.18% |
Linus Torvalds | 3 | 1.48% | 1 | 5.88% |
Nicholas Piggin | 2 | 0.99% | 1 | 5.88% |
Rob Clark | 2 | 0.99% | 1 | 5.88% |
Konstantin Khlebnikov | 2 | 0.99% | 1 | 5.88% |
Thomas Hellstrom | 2 | 0.99% | 2 | 11.76% |
Total | 203 | 100.00% | 17 | 100.00% |
static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
{
#ifdef __alpha__
return dev->hose->dense_mem_base;
#else
return 0;
#endif
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dave Airlie | 19 | 67.86% | 2 | 40.00% |
Linus Torvalds | 7 | 25.00% | 1 | 20.00% |
Daniel Vetter | 1 | 3.57% | 1 | 20.00% |
Benjamin Herrenschmidt | 1 | 3.57% | 1 | 20.00% |
Total | 28 | 100.00% | 5 | 100.00% |
/**
* mmap DMA memory.
*
* \param file_priv DRM file private.
* \param vma virtual memory area.
* \return zero on success or a negative number on failure.
*
* If the virtual memory area has no offset associated with it then it's a DMA
* area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist,
* checks that the restricted flag is not set, sets the virtual memory operations
* 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)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev;
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",
vma->vm_start, vma->vm_end, vma->vm_pgoff);
if (!priv->authenticated)
return -EACCES;
/* We check for "dma". On Apple's UniNorth, it's valid to have
* the AGP mapped at physical address 0
* --BenH.
*/
if (!vma->vm_pgoff
#if IS_ENABLED(CONFIG_AGP)
&& (!dev->agp
|| dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)
#endif
)
return drm_mmap_dma(filp, vma);
if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) {
DRM_ERROR("Could not find map\n");
return -EINVAL;
}
map = drm_hash_entry(hash, struct drm_map_list, hash)->map;
if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN)))
return -EPERM;
/* 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_WRITE | VM_MAYWRITE);
#if defined(__i386__) || defined(__x86_64__)
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) {
#if !defined(__arm__)
case _DRM_AGP:
if (dev->agp && dev->agp->cant_use_aperture) {
/*
* On some platforms we can't talk to bus dma address from the CPU, so for
* memory of type DRM_AGP, we'll deal with sorting out the real physical
* pages and mappings in fault()
*/
#if defined(__powerpc__)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#endif
vma->vm_ops = &drm_vm_ops;
break;
}
/* fall through to _DRM_FRAME_BUFFER... */
#endif
case _DRM_FRAME_BUFFER:
case _DRM_REGISTERS:
offset = drm_core_get_reg_ofs(dev);
vma->vm_page_prot = drm_io_prot(map, vma);
if (io_remap_pfn_range(vma, vma->vm_start,
(map->offset + offset) >> PAGE_SHIFT,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx,"
" offset = 0x%llx\n",
map->type,
vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
vma->vm_ops = &drm_vm_ops;
break;
case _DRM_CONSISTENT:
/* Consistent memory is really like shared memory. But
* it's allocated in a different way, so avoid fault */
if (remap_pfn_range(vma, vma->vm_start,
page_to_pfn(virt_to_page(map->handle)),
vma->vm_end - vma->vm_start, vma->vm_page_prot))
return -EAGAIN;
vma->vm_page_prot = drm_dma_prot(map->type, vma);
/* fall through to _DRM_SHM */
case _DRM_SHM:
vma->vm_ops = &drm_vm_shm_ops;
vma->vm_private_data = (void *)map;
break;
case _DRM_SCATTER_GATHER:
vma->vm_ops = &drm_vm_sg_ops;
vma->vm_private_data = (void *)map;
vma->vm_page_prot = drm_dma_prot(map->type, vma);
break;
default:
return -EINVAL; /* This should never happen. */
}
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
drm_vm_open_locked(dev, vma);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 255 | 43.59% | 3 | 6.38% |
Linus Torvalds | 142 | 24.27% | 8 | 17.02% |
Dave Airlie | 46 | 7.86% | 16 | 34.04% |
Hugh Dickins | 40 | 6.84% | 1 | 2.13% |
Benjamin Herrenschmidt | 39 | 6.67% | 5 | 10.64% |
Thomas Hellstrom | 32 | 5.47% | 3 | 6.38% |
Jordan Crouse | 9 | 1.54% | 1 | 2.13% |
Daniel Vetter | 8 | 1.37% | 4 | 8.51% |
Randy Dunlap | 5 | 0.85% | 1 | 2.13% |
Nicholas Piggin | 4 | 0.68% | 2 | 4.26% |
Konstantin Khlebnikov | 2 | 0.34% | 1 | 2.13% |
Rob Clark | 2 | 0.34% | 1 | 2.13% |
Jesse Barnes | 1 | 0.17% | 1 | 2.13% |
Total | 585 | 100.00% | 47 | 100.00% |
int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev;
int ret;
if (drm_device_is_unplugged(dev))
return -ENODEV;
mutex_lock(&dev->struct_mutex);
ret = drm_mmap_locked(filp, vma);
mutex_unlock(&dev->struct_mutex);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Thomas Hellstrom | 60 | 77.92% | 1 | 20.00% |
Dave Airlie | 16 | 20.78% | 3 | 60.00% |
Daniel Vetter | 1 | 1.30% | 1 | 20.00% |
Total | 77 | 100.00% | 5 | 100.00% |
EXPORT_SYMBOL(drm_legacy_mmap);
void drm_legacy_vma_flush(struct drm_device *dev)
{
struct drm_vma_entry *vma, *vma_temp;
/* Clear vma list (only needed for legacy drivers) */
list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) {
list_del(&vma->head);
kfree(vma);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
David Herrmann | 44 | 100.00% | 1 | 100.00% |
Total | 44 | 100.00% | 1 | 100.00% |
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 631 | 24.20% | 5 | 5.38% |
Linus Torvalds | 606 | 23.25% | 11 | 11.83% |
Dave Airlie | 499 | 19.14% | 26 | 27.96% |
Thomas Hellstrom | 157 | 6.02% | 3 | 3.23% |
Nicholas Piggin | 152 | 5.83% | 2 | 2.15% |
Benjamin Herrenschmidt | 122 | 4.68% | 6 | 6.45% |
George Sapountzis | 78 | 2.99% | 1 | 1.08% |
David Herrmann | 70 | 2.69% | 3 | 3.23% |
Chris Wilson | 48 | 1.84% | 1 | 1.08% |
Hugh Dickins | 40 | 1.53% | 1 | 1.08% |
Dave Jiang | 38 | 1.46% | 1 | 1.08% |
Andrew Lutomirski | 27 | 1.04% | 2 | 2.15% |
Daniel Vetter | 20 | 0.77% | 6 | 6.45% |
Rob Clark | 18 | 0.69% | 1 | 1.08% |
Jordan Crouse | 14 | 0.54% | 1 | 1.08% |
Ingo Molnar | 11 | 0.42% | 2 | 2.15% |
Tony Luck | 11 | 0.42% | 1 | 1.08% |
Dan Carpenter | 10 | 0.38% | 1 | 1.08% |
Eric Anholt | 7 | 0.27% | 2 | 2.15% |
Randy Dunlap | 5 | 0.19% | 1 | 1.08% |
Ross Zwisler | 5 | 0.19% | 1 | 1.08% |
Huacai Chen | 5 | 0.19% | 1 | 1.08% |
Jan Kara | 4 | 0.15% | 1 | 1.08% |
Alexey Dobriyan | 4 | 0.15% | 1 | 1.08% |
Konstantin Khlebnikov | 4 | 0.15% | 1 | 1.08% |
Ben Hutchings | 4 | 0.15% | 1 | 1.08% |
Tejun Heo | 3 | 0.12% | 1 | 1.08% |
Paul Gortmaker | 3 | 0.12% | 1 | 1.08% |
Ville Syrjälä | 3 | 0.12% | 1 | 1.08% |
Al Viro | 2 | 0.08% | 1 | 1.08% |
Andrew Morton | 1 | 0.04% | 1 | 1.08% |
Michael Opdenacker | 1 | 0.04% | 1 | 1.08% |
Christoph Hellwig | 1 | 0.04% | 1 | 1.08% |
David Howells | 1 | 0.04% | 1 | 1.08% |
Adrian Bunk | 1 | 0.04% | 1 | 1.08% |
Jesse Barnes | 1 | 0.04% | 1 | 1.08% |
Total | 2607 | 100.00% | 93 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.