2 * Copyright (C) 2016 Red Hat
3 * Author: Rob Clark <robdclark@gmail.com>
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.
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
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/>.
23 msm_gem_address_space_destroy(struct kref
*kref
)
25 struct msm_gem_address_space
*aspace
= container_of(kref
,
26 struct msm_gem_address_space
, kref
);
28 drm_mm_takedown(&aspace
->mm
);
30 aspace
->mmu
->funcs
->destroy(aspace
->mmu
);
35 void msm_gem_address_space_put(struct msm_gem_address_space
*aspace
)
38 kref_put(&aspace
->kref
, msm_gem_address_space_destroy
);
42 msm_gem_unmap_vma(struct msm_gem_address_space
*aspace
,
43 struct msm_gem_vma
*vma
, struct sg_table
*sgt
)
45 if (!aspace
|| !vma
->iova
)
49 unsigned size
= vma
->node
.size
<< PAGE_SHIFT
;
50 aspace
->mmu
->funcs
->unmap(aspace
->mmu
, vma
->iova
, sgt
, size
);
53 spin_lock(&aspace
->lock
);
54 drm_mm_remove_node(&vma
->node
);
55 spin_unlock(&aspace
->lock
);
59 msm_gem_address_space_put(aspace
);
63 msm_gem_map_vma(struct msm_gem_address_space
*aspace
,
64 struct msm_gem_vma
*vma
, struct sg_table
*sgt
, int npages
)
68 spin_lock(&aspace
->lock
);
69 if (WARN_ON(drm_mm_node_allocated(&vma
->node
))) {
70 spin_unlock(&aspace
->lock
);
74 ret
= drm_mm_insert_node(&aspace
->mm
, &vma
->node
, npages
);
75 spin_unlock(&aspace
->lock
);
80 vma
->iova
= vma
->node
.start
<< PAGE_SHIFT
;
83 unsigned size
= npages
<< PAGE_SHIFT
;
84 ret
= aspace
->mmu
->funcs
->map(aspace
->mmu
, vma
->iova
, sgt
,
85 size
, IOMMU_READ
| IOMMU_WRITE
);
88 /* Get a reference to the aspace to keep it around */
89 kref_get(&aspace
->kref
);
94 struct msm_gem_address_space
*
95 msm_gem_address_space_create(struct device
*dev
, struct iommu_domain
*domain
,
98 struct msm_gem_address_space
*aspace
;
100 aspace
= kzalloc(sizeof(*aspace
), GFP_KERNEL
);
102 return ERR_PTR(-ENOMEM
);
104 spin_lock_init(&aspace
->lock
);
106 aspace
->mmu
= msm_iommu_new(dev
, domain
);
108 drm_mm_init(&aspace
->mm
, (domain
->geometry
.aperture_start
>> PAGE_SHIFT
),
109 (domain
->geometry
.aperture_end
>> PAGE_SHIFT
) - 1);
111 kref_init(&aspace
->kref
);