linux/drivers/gpu/drm/msm/msm_gem_vma.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2016 Red Hat
   3 * Author: Rob Clark <robdclark@gmail.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of the GNU General Public License version 2 as published by
   7 * the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program.  If not, see <http://www.gnu.org/licenses/>.
  16 */
  17
  18#include "msm_drv.h"
  19#include "msm_gem.h"
  20#include "msm_mmu.h"
  21
  22void
  23msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
  24                struct msm_gem_vma *vma, struct sg_table *sgt)
  25{
  26        if (!vma->iova)
  27                return;
  28
  29        if (aspace->mmu) {
  30                unsigned size = vma->node.size << PAGE_SHIFT;
  31                aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, sgt, size);
  32        }
  33
  34        drm_mm_remove_node(&vma->node);
  35
  36        vma->iova = 0;
  37}
  38
  39int
  40msm_gem_map_vma(struct msm_gem_address_space *aspace,
  41                struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
  42{
  43        int ret;
  44
  45        if (WARN_ON(drm_mm_node_allocated(&vma->node)))
  46                return 0;
  47
  48        ret = drm_mm_insert_node(&aspace->mm, &vma->node, npages);
  49        if (ret)
  50                return ret;
  51
  52        vma->iova = vma->node.start << PAGE_SHIFT;
  53
  54        if (aspace->mmu) {
  55                unsigned size = npages << PAGE_SHIFT;
  56                ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
  57                                size, IOMMU_READ | IOMMU_WRITE);
  58        }
  59
  60        return ret;
  61}
  62
  63void
  64msm_gem_address_space_destroy(struct msm_gem_address_space *aspace)
  65{
  66        drm_mm_takedown(&aspace->mm);
  67        if (aspace->mmu)
  68                aspace->mmu->funcs->destroy(aspace->mmu);
  69        kfree(aspace);
  70}
  71
  72struct msm_gem_address_space *
  73msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
  74                const char *name)
  75{
  76        struct msm_gem_address_space *aspace;
  77
  78        aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);
  79        if (!aspace)
  80                return ERR_PTR(-ENOMEM);
  81
  82        aspace->name = name;
  83        aspace->mmu = msm_iommu_new(dev, domain);
  84
  85        drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT),
  86                        (domain->geometry.aperture_end >> PAGE_SHIFT) - 1);
  87
  88        return aspace;
  89}
  90