diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-03-26 08:43:12 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-03-31 09:32:12 -0400 |
commit | d5f1a81ccb8947828f60b50d8e9ed7617259a9ec (patch) | |
tree | fb65283a8874b22ed08cc92aefacf3970a93ffb5 /drivers/iommu/tegra-smmu.c | |
parent | e1fd1eaa3323b3ea68f2ad3116b8cbe1f34cb2a2 (diff) |
iommu/tegra-smmu: Make use of domain_alloc and domain_free
Implement domain_alloc and domain_free iommu-ops as a
replacement for domain_init/domain_destroy.
Tested-by: Thierry Reding <treding@nvidia.com>
Acked-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/tegra-smmu.c')
-rw-r--r-- | drivers/iommu/tegra-smmu.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 6e134c7c227f..720829724d86 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c | |||
@@ -31,7 +31,7 @@ struct tegra_smmu { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | struct tegra_smmu_as { | 33 | struct tegra_smmu_as { |
34 | struct iommu_domain *domain; | 34 | struct iommu_domain domain; |
35 | struct tegra_smmu *smmu; | 35 | struct tegra_smmu *smmu; |
36 | unsigned int use_count; | 36 | unsigned int use_count; |
37 | struct page *count; | 37 | struct page *count; |
@@ -40,6 +40,11 @@ struct tegra_smmu_as { | |||
40 | u32 attr; | 40 | u32 attr; |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static struct tegra_smmu_as *to_smmu_as(struct iommu_domain *dom) | ||
44 | { | ||
45 | return container_of(dom, struct tegra_smmu_as, domain); | ||
46 | } | ||
47 | |||
43 | static inline void smmu_writel(struct tegra_smmu *smmu, u32 value, | 48 | static inline void smmu_writel(struct tegra_smmu *smmu, u32 value, |
44 | unsigned long offset) | 49 | unsigned long offset) |
45 | { | 50 | { |
@@ -224,30 +229,32 @@ static bool tegra_smmu_capable(enum iommu_cap cap) | |||
224 | return false; | 229 | return false; |
225 | } | 230 | } |
226 | 231 | ||
227 | static int tegra_smmu_domain_init(struct iommu_domain *domain) | 232 | static struct iommu_domain *tegra_smmu_domain_alloc(unsigned type) |
228 | { | 233 | { |
229 | struct tegra_smmu_as *as; | 234 | struct tegra_smmu_as *as; |
230 | unsigned int i; | 235 | unsigned int i; |
231 | uint32_t *pd; | 236 | uint32_t *pd; |
232 | 237 | ||
238 | if (type != IOMMU_DOMAIN_UNMANAGED) | ||
239 | return NULL; | ||
240 | |||
233 | as = kzalloc(sizeof(*as), GFP_KERNEL); | 241 | as = kzalloc(sizeof(*as), GFP_KERNEL); |
234 | if (!as) | 242 | if (!as) |
235 | return -ENOMEM; | 243 | return NULL; |
236 | 244 | ||
237 | as->attr = SMMU_PD_READABLE | SMMU_PD_WRITABLE | SMMU_PD_NONSECURE; | 245 | as->attr = SMMU_PD_READABLE | SMMU_PD_WRITABLE | SMMU_PD_NONSECURE; |
238 | as->domain = domain; | ||
239 | 246 | ||
240 | as->pd = alloc_page(GFP_KERNEL | __GFP_DMA); | 247 | as->pd = alloc_page(GFP_KERNEL | __GFP_DMA); |
241 | if (!as->pd) { | 248 | if (!as->pd) { |
242 | kfree(as); | 249 | kfree(as); |
243 | return -ENOMEM; | 250 | return NULL; |
244 | } | 251 | } |
245 | 252 | ||
246 | as->count = alloc_page(GFP_KERNEL); | 253 | as->count = alloc_page(GFP_KERNEL); |
247 | if (!as->count) { | 254 | if (!as->count) { |
248 | __free_page(as->pd); | 255 | __free_page(as->pd); |
249 | kfree(as); | 256 | kfree(as); |
250 | return -ENOMEM; | 257 | return NULL; |
251 | } | 258 | } |
252 | 259 | ||
253 | /* clear PDEs */ | 260 | /* clear PDEs */ |
@@ -264,14 +271,12 @@ static int tegra_smmu_domain_init(struct iommu_domain *domain) | |||
264 | for (i = 0; i < SMMU_NUM_PDE; i++) | 271 | for (i = 0; i < SMMU_NUM_PDE; i++) |
265 | pd[i] = 0; | 272 | pd[i] = 0; |
266 | 273 | ||
267 | domain->priv = as; | 274 | return &as->domain; |
268 | |||
269 | return 0; | ||
270 | } | 275 | } |
271 | 276 | ||
272 | static void tegra_smmu_domain_destroy(struct iommu_domain *domain) | 277 | static void tegra_smmu_domain_free(struct iommu_domain *domain) |
273 | { | 278 | { |
274 | struct tegra_smmu_as *as = domain->priv; | 279 | struct tegra_smmu_as *as = to_smmu_as(domain); |
275 | 280 | ||
276 | /* TODO: free page directory and page tables */ | 281 | /* TODO: free page directory and page tables */ |
277 | ClearPageReserved(as->pd); | 282 | ClearPageReserved(as->pd); |
@@ -395,7 +400,7 @@ static int tegra_smmu_attach_dev(struct iommu_domain *domain, | |||
395 | struct device *dev) | 400 | struct device *dev) |
396 | { | 401 | { |
397 | struct tegra_smmu *smmu = dev->archdata.iommu; | 402 | struct tegra_smmu *smmu = dev->archdata.iommu; |
398 | struct tegra_smmu_as *as = domain->priv; | 403 | struct tegra_smmu_as *as = to_smmu_as(domain); |
399 | struct device_node *np = dev->of_node; | 404 | struct device_node *np = dev->of_node; |
400 | struct of_phandle_args args; | 405 | struct of_phandle_args args; |
401 | unsigned int index = 0; | 406 | unsigned int index = 0; |
@@ -428,7 +433,7 @@ static int tegra_smmu_attach_dev(struct iommu_domain *domain, | |||
428 | 433 | ||
429 | static void tegra_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) | 434 | static void tegra_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) |
430 | { | 435 | { |
431 | struct tegra_smmu_as *as = domain->priv; | 436 | struct tegra_smmu_as *as = to_smmu_as(domain); |
432 | struct device_node *np = dev->of_node; | 437 | struct device_node *np = dev->of_node; |
433 | struct tegra_smmu *smmu = as->smmu; | 438 | struct tegra_smmu *smmu = as->smmu; |
434 | struct of_phandle_args args; | 439 | struct of_phandle_args args; |
@@ -524,7 +529,7 @@ static void as_put_pte(struct tegra_smmu_as *as, dma_addr_t iova) | |||
524 | static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova, | 529 | static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova, |
525 | phys_addr_t paddr, size_t size, int prot) | 530 | phys_addr_t paddr, size_t size, int prot) |
526 | { | 531 | { |
527 | struct tegra_smmu_as *as = domain->priv; | 532 | struct tegra_smmu_as *as = to_smmu_as(domain); |
528 | struct tegra_smmu *smmu = as->smmu; | 533 | struct tegra_smmu *smmu = as->smmu; |
529 | unsigned long offset; | 534 | unsigned long offset; |
530 | struct page *page; | 535 | struct page *page; |
@@ -548,7 +553,7 @@ static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova, | |||
548 | static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova, | 553 | static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova, |
549 | size_t size) | 554 | size_t size) |
550 | { | 555 | { |
551 | struct tegra_smmu_as *as = domain->priv; | 556 | struct tegra_smmu_as *as = to_smmu_as(domain); |
552 | struct tegra_smmu *smmu = as->smmu; | 557 | struct tegra_smmu *smmu = as->smmu; |
553 | unsigned long offset; | 558 | unsigned long offset; |
554 | struct page *page; | 559 | struct page *page; |
@@ -572,7 +577,7 @@ static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova, | |||
572 | static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain, | 577 | static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain, |
573 | dma_addr_t iova) | 578 | dma_addr_t iova) |
574 | { | 579 | { |
575 | struct tegra_smmu_as *as = domain->priv; | 580 | struct tegra_smmu_as *as = to_smmu_as(domain); |
576 | struct page *page; | 581 | struct page *page; |
577 | unsigned long pfn; | 582 | unsigned long pfn; |
578 | u32 *pte; | 583 | u32 *pte; |
@@ -633,8 +638,8 @@ static void tegra_smmu_remove_device(struct device *dev) | |||
633 | 638 | ||
634 | static const struct iommu_ops tegra_smmu_ops = { | 639 | static const struct iommu_ops tegra_smmu_ops = { |
635 | .capable = tegra_smmu_capable, | 640 | .capable = tegra_smmu_capable, |
636 | .domain_init = tegra_smmu_domain_init, | 641 | .domain_alloc = tegra_smmu_domain_alloc, |
637 | .domain_destroy = tegra_smmu_domain_destroy, | 642 | .domain_free = tegra_smmu_domain_free, |
638 | .attach_dev = tegra_smmu_attach_dev, | 643 | .attach_dev = tegra_smmu_attach_dev, |
639 | .detach_dev = tegra_smmu_detach_dev, | 644 | .detach_dev = tegra_smmu_detach_dev, |
640 | .add_device = tegra_smmu_add_device, | 645 | .add_device = tegra_smmu_add_device, |