Linux Audio

Check our new training course

Loading...
v4.6
 
  1/*
  2 * Copyright (C) 2013 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_mmu.h"
 20
 21struct msm_iommu {
 22	struct msm_mmu base;
 23	struct iommu_domain *domain;
 24};
 25#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
 26
 27static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
 28		unsigned long iova, int flags, void *arg)
 29{
 30	pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
 
 
 
 31	return 0;
 32}
 33
 34static int msm_iommu_attach(struct msm_mmu *mmu, const char * const *names,
 35			    int cnt)
 36{
 37	struct msm_iommu *iommu = to_msm_iommu(mmu);
 
 38	return iommu_attach_device(iommu->domain, mmu->dev);
 39}
 40
 41static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names,
 42			     int cnt)
 43{
 44	struct msm_iommu *iommu = to_msm_iommu(mmu);
 
 45	iommu_detach_device(iommu->domain, mmu->dev);
 46}
 47
 48static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
 49		struct sg_table *sgt, unsigned len, int prot)
 50{
 51	struct msm_iommu *iommu = to_msm_iommu(mmu);
 52	struct iommu_domain *domain = iommu->domain;
 53	struct scatterlist *sg;
 54	unsigned int da = iova;
 55	unsigned int i, j;
 56	int ret;
 57
 58	if (!domain || !sgt)
 59		return -EINVAL;
 60
 61	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
 62		u32 pa = sg_phys(sg) - sg->offset;
 63		size_t bytes = sg->length + sg->offset;
 64
 65		VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
 66
 67		ret = iommu_map(domain, da, pa, bytes, prot);
 68		if (ret)
 69			goto fail;
 70
 71		da += bytes;
 72	}
 73
 74	return 0;
 75
 76fail:
 77	da = iova;
 78
 79	for_each_sg(sgt->sgl, sg, i, j) {
 80		size_t bytes = sg->length + sg->offset;
 81		iommu_unmap(domain, da, bytes);
 82		da += bytes;
 83	}
 84	return ret;
 85}
 86
 87static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,
 88		struct sg_table *sgt, unsigned len)
 89{
 90	struct msm_iommu *iommu = to_msm_iommu(mmu);
 91	struct iommu_domain *domain = iommu->domain;
 92	struct scatterlist *sg;
 93	unsigned int da = iova;
 94	int i;
 95
 96	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
 97		size_t bytes = sg->length + sg->offset;
 98		size_t unmapped;
 99
100		unmapped = iommu_unmap(domain, da, bytes);
101		if (unmapped < bytes)
102			return unmapped;
103
104		VERB("unmap[%d]: %08x(%zx)", i, iova, bytes);
105
106		BUG_ON(!PAGE_ALIGNED(bytes));
107
108		da += bytes;
109	}
110
111	return 0;
112}
113
114static void msm_iommu_destroy(struct msm_mmu *mmu)
115{
116	struct msm_iommu *iommu = to_msm_iommu(mmu);
117	iommu_domain_free(iommu->domain);
118	kfree(iommu);
119}
120
121static const struct msm_mmu_funcs funcs = {
122		.attach = msm_iommu_attach,
123		.detach = msm_iommu_detach,
124		.map = msm_iommu_map,
125		.unmap = msm_iommu_unmap,
126		.destroy = msm_iommu_destroy,
127};
128
129struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
130{
131	struct msm_iommu *iommu;
132
133	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
134	if (!iommu)
135		return ERR_PTR(-ENOMEM);
136
137	iommu->domain = domain;
138	msm_mmu_init(&iommu->base, dev, &funcs);
139	iommu_set_fault_handler(domain, msm_fault_handler, dev);
140
141	return &iommu->base;
142}
v5.4
 1// SPDX-License-Identifier: GPL-2.0-only
 2/*
 3 * Copyright (C) 2013 Red Hat
 4 * Author: Rob Clark <robdclark@gmail.com>
 
 
 
 
 
 
 
 
 
 
 
 
 5 */
 6
 7#include "msm_drv.h"
 8#include "msm_mmu.h"
 9
10struct msm_iommu {
11	struct msm_mmu base;
12	struct iommu_domain *domain;
13};
14#define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
15
16static int msm_fault_handler(struct iommu_domain *domain, struct device *dev,
17		unsigned long iova, int flags, void *arg)
18{
19	struct msm_iommu *iommu = arg;
20	if (iommu->base.handler)
21		return iommu->base.handler(iommu->base.arg, iova, flags);
22	pr_warn_ratelimited("*** fault: iova=%16lx, flags=%d\n", iova, flags);
23	return 0;
24}
25
26static int msm_iommu_attach(struct msm_mmu *mmu, const char * const *names,
27			    int cnt)
28{
29	struct msm_iommu *iommu = to_msm_iommu(mmu);
30
31	return iommu_attach_device(iommu->domain, mmu->dev);
32}
33
34static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names,
35			     int cnt)
36{
37	struct msm_iommu *iommu = to_msm_iommu(mmu);
38
39	iommu_detach_device(iommu->domain, mmu->dev);
40}
41
42static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
43		struct sg_table *sgt, unsigned len, int prot)
44{
45	struct msm_iommu *iommu = to_msm_iommu(mmu);
46	size_t ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
48	ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot);
49	WARN_ON(!ret);
50
51	return (ret == len) ? 0 : -EINVAL;
 
 
 
 
 
52}
53
54static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len)
 
55{
56	struct msm_iommu *iommu = to_msm_iommu(mmu);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
58	iommu_unmap(iommu->domain, iova, len);
 
59
60	return 0;
61}
62
63static void msm_iommu_destroy(struct msm_mmu *mmu)
64{
65	struct msm_iommu *iommu = to_msm_iommu(mmu);
66	iommu_domain_free(iommu->domain);
67	kfree(iommu);
68}
69
70static const struct msm_mmu_funcs funcs = {
71		.attach = msm_iommu_attach,
72		.detach = msm_iommu_detach,
73		.map = msm_iommu_map,
74		.unmap = msm_iommu_unmap,
75		.destroy = msm_iommu_destroy,
76};
77
78struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
79{
80	struct msm_iommu *iommu;
81
82	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
83	if (!iommu)
84		return ERR_PTR(-ENOMEM);
85
86	iommu->domain = domain;
87	msm_mmu_init(&iommu->base, dev, &funcs);
88	iommu_set_fault_handler(domain, msm_fault_handler, iommu);
89
90	return &iommu->base;
91}