Linux Audio

Check our new training course

Yocto / OpenEmbedded training

Feb 10-13, 2025
Register
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}
v4.17
  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 *domain, struct device *dev,
 28		unsigned long iova, int flags, void *arg)
 29{
 30	struct msm_iommu *iommu = arg;
 31	if (iommu->base.handler)
 32		return iommu->base.handler(iommu->base.arg, iova, flags);
 33	pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
 34	return 0;
 35}
 36
 37static int msm_iommu_attach(struct msm_mmu *mmu, const char * const *names,
 38			    int cnt)
 39{
 40	struct msm_iommu *iommu = to_msm_iommu(mmu);
 41	int ret;
 42
 43	pm_runtime_get_sync(mmu->dev);
 44	ret = iommu_attach_device(iommu->domain, mmu->dev);
 45	pm_runtime_put_sync(mmu->dev);
 46
 47	return ret;
 48}
 49
 50static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names,
 51			     int cnt)
 52{
 53	struct msm_iommu *iommu = to_msm_iommu(mmu);
 54
 55	pm_runtime_get_sync(mmu->dev);
 56	iommu_detach_device(iommu->domain, mmu->dev);
 57	pm_runtime_put_sync(mmu->dev);
 58}
 59
 60static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
 61		struct sg_table *sgt, unsigned len, int prot)
 62{
 63	struct msm_iommu *iommu = to_msm_iommu(mmu);
 64	size_t ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 65
 66//	pm_runtime_get_sync(mmu->dev);
 67	ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot);
 68//	pm_runtime_put_sync(mmu->dev);
 69	WARN_ON(ret < 0);
 70
 71	return (ret == len) ? 0 : -EINVAL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 72}
 73
 74static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova,
 75		struct sg_table *sgt, unsigned len)
 76{
 77	struct msm_iommu *iommu = to_msm_iommu(mmu);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 78
 79	pm_runtime_get_sync(mmu->dev);
 80	iommu_unmap(iommu->domain, iova, len);
 81	pm_runtime_put_sync(mmu->dev);
 82
 83	return 0;
 84}
 85
 86static void msm_iommu_destroy(struct msm_mmu *mmu)
 87{
 88	struct msm_iommu *iommu = to_msm_iommu(mmu);
 89	iommu_domain_free(iommu->domain);
 90	kfree(iommu);
 91}
 92
 93static const struct msm_mmu_funcs funcs = {
 94		.attach = msm_iommu_attach,
 95		.detach = msm_iommu_detach,
 96		.map = msm_iommu_map,
 97		.unmap = msm_iommu_unmap,
 98		.destroy = msm_iommu_destroy,
 99};
100
101struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
102{
103	struct msm_iommu *iommu;
104
105	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
106	if (!iommu)
107		return ERR_PTR(-ENOMEM);
108
109	iommu->domain = domain;
110	msm_mmu_init(&iommu->base, dev, &funcs);
111	iommu_set_fault_handler(domain, msm_fault_handler, iommu);
112
113	return &iommu->base;
114}