.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2011,2016 Samsung Electronics Co., Ltd. |
---|
3 | 4 | * http://www.samsung.com |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License version 2 as |
---|
7 | | - * published by the Free Software Foundation. |
---|
8 | 5 | */ |
---|
9 | 6 | |
---|
10 | 7 | #ifdef CONFIG_EXYNOS_IOMMU_DEBUG |
---|
.. | .. |
---|
176 | 173 | #define REG_V5_FAULT_AR_VA 0x070 |
---|
177 | 174 | #define REG_V5_FAULT_AW_VA 0x080 |
---|
178 | 175 | |
---|
179 | | -#define has_sysmmu(dev) (dev->archdata.iommu != NULL) |
---|
| 176 | +#define has_sysmmu(dev) (dev_iommu_priv_get(dev) != NULL) |
---|
180 | 177 | |
---|
181 | 178 | static struct device *dma_dev; |
---|
182 | 179 | static struct kmem_cache *lv2table_kmem_cache; |
---|
.. | .. |
---|
229 | 226 | }; |
---|
230 | 227 | |
---|
231 | 228 | /* |
---|
232 | | - * This structure is attached to dev.archdata.iommu of the master device |
---|
| 229 | + * This structure is attached to dev->iommu->priv of the master device |
---|
233 | 230 | * on device add, contains a list of SYSMMU controllers defined by device tree, |
---|
234 | 231 | * which are bound to given master device. It is usually referenced by 'owner' |
---|
235 | 232 | * pointer. |
---|
.. | .. |
---|
569 | 566 | |
---|
570 | 567 | static const struct iommu_ops exynos_iommu_ops; |
---|
571 | 568 | |
---|
572 | | -static int __init exynos_sysmmu_probe(struct platform_device *pdev) |
---|
| 569 | +static int exynos_sysmmu_probe(struct platform_device *pdev) |
---|
573 | 570 | { |
---|
574 | 571 | int irq, ret; |
---|
575 | 572 | struct device *dev = &pdev->dev; |
---|
.. | .. |
---|
586 | 583 | return PTR_ERR(data->sfrbase); |
---|
587 | 584 | |
---|
588 | 585 | irq = platform_get_irq(pdev, 0); |
---|
589 | | - if (irq <= 0) { |
---|
590 | | - dev_err(dev, "Unable to find IRQ resource\n"); |
---|
| 586 | + if (irq <= 0) |
---|
591 | 587 | return irq; |
---|
592 | | - } |
---|
593 | 588 | |
---|
594 | 589 | ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, |
---|
595 | 590 | dev_name(dev), data); |
---|
.. | .. |
---|
640 | 635 | |
---|
641 | 636 | ret = iommu_device_register(&data->iommu); |
---|
642 | 637 | if (ret) |
---|
643 | | - return ret; |
---|
| 638 | + goto err_iommu_register; |
---|
644 | 639 | |
---|
645 | 640 | platform_set_drvdata(pdev, data); |
---|
646 | 641 | |
---|
.. | .. |
---|
667 | 662 | pm_runtime_enable(dev); |
---|
668 | 663 | |
---|
669 | 664 | return 0; |
---|
| 665 | + |
---|
| 666 | +err_iommu_register: |
---|
| 667 | + iommu_device_sysfs_remove(&data->iommu); |
---|
| 668 | + return ret; |
---|
670 | 669 | } |
---|
671 | 670 | |
---|
672 | 671 | static int __maybe_unused exynos_sysmmu_suspend(struct device *dev) |
---|
.. | .. |
---|
675 | 674 | struct device *master = data->master; |
---|
676 | 675 | |
---|
677 | 676 | if (master) { |
---|
678 | | - struct exynos_iommu_owner *owner = master->archdata.iommu; |
---|
| 677 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); |
---|
679 | 678 | |
---|
680 | 679 | mutex_lock(&owner->rpm_lock); |
---|
681 | 680 | if (data->domain) { |
---|
.. | .. |
---|
693 | 692 | struct device *master = data->master; |
---|
694 | 693 | |
---|
695 | 694 | if (master) { |
---|
696 | | - struct exynos_iommu_owner *owner = master->archdata.iommu; |
---|
| 695 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(master); |
---|
697 | 696 | |
---|
698 | 697 | mutex_lock(&owner->rpm_lock); |
---|
699 | 698 | if (data->domain) { |
---|
.. | .. |
---|
726 | 725 | } |
---|
727 | 726 | }; |
---|
728 | 727 | |
---|
729 | | -static inline void update_pte(sysmmu_pte_t *ent, sysmmu_pte_t val) |
---|
| 728 | +static inline void exynos_iommu_set_pte(sysmmu_pte_t *ent, sysmmu_pte_t val) |
---|
730 | 729 | { |
---|
731 | 730 | dma_sync_single_for_cpu(dma_dev, virt_to_phys(ent), sizeof(*ent), |
---|
732 | 731 | DMA_TO_DEVICE); |
---|
.. | .. |
---|
842 | 841 | static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain, |
---|
843 | 842 | struct device *dev) |
---|
844 | 843 | { |
---|
845 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
---|
846 | 844 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
---|
| 845 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
---|
847 | 846 | phys_addr_t pagetable = virt_to_phys(domain->pgtable); |
---|
848 | 847 | struct sysmmu_drvdata *data, *next; |
---|
849 | 848 | unsigned long flags; |
---|
.. | .. |
---|
880 | 879 | static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain, |
---|
881 | 880 | struct device *dev) |
---|
882 | 881 | { |
---|
883 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
---|
884 | 882 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
---|
| 883 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
---|
885 | 884 | struct sysmmu_drvdata *data; |
---|
886 | 885 | phys_addr_t pagetable = virt_to_phys(domain->pgtable); |
---|
887 | 886 | unsigned long flags; |
---|
.. | .. |
---|
938 | 937 | if (!pent) |
---|
939 | 938 | return ERR_PTR(-ENOMEM); |
---|
940 | 939 | |
---|
941 | | - update_pte(sent, mk_lv1ent_page(virt_to_phys(pent))); |
---|
| 940 | + exynos_iommu_set_pte(sent, mk_lv1ent_page(virt_to_phys(pent))); |
---|
942 | 941 | kmemleak_ignore(pent); |
---|
943 | 942 | *pgcounter = NUM_LV2ENTRIES; |
---|
944 | 943 | handle = dma_map_single(dma_dev, pent, LV2TABLE_SIZE, |
---|
.. | .. |
---|
999 | 998 | *pgcnt = 0; |
---|
1000 | 999 | } |
---|
1001 | 1000 | |
---|
1002 | | - update_pte(sent, mk_lv1ent_sect(paddr, prot)); |
---|
| 1001 | + exynos_iommu_set_pte(sent, mk_lv1ent_sect(paddr, prot)); |
---|
1003 | 1002 | |
---|
1004 | 1003 | spin_lock(&domain->lock); |
---|
1005 | 1004 | if (lv1ent_page_zero(sent)) { |
---|
.. | .. |
---|
1023 | 1022 | if (WARN_ON(!lv2ent_fault(pent))) |
---|
1024 | 1023 | return -EADDRINUSE; |
---|
1025 | 1024 | |
---|
1026 | | - update_pte(pent, mk_lv2ent_spage(paddr, prot)); |
---|
| 1025 | + exynos_iommu_set_pte(pent, mk_lv2ent_spage(paddr, prot)); |
---|
1027 | 1026 | *pgcnt -= 1; |
---|
1028 | 1027 | } else { /* size == LPAGE_SIZE */ |
---|
1029 | 1028 | int i; |
---|
.. | .. |
---|
1078 | 1077 | */ |
---|
1079 | 1078 | static int exynos_iommu_map(struct iommu_domain *iommu_domain, |
---|
1080 | 1079 | unsigned long l_iova, phys_addr_t paddr, size_t size, |
---|
1081 | | - int prot) |
---|
| 1080 | + int prot, gfp_t gfp) |
---|
1082 | 1081 | { |
---|
1083 | 1082 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
---|
1084 | 1083 | sysmmu_pte_t *entry; |
---|
.. | .. |
---|
1133 | 1132 | } |
---|
1134 | 1133 | |
---|
1135 | 1134 | static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain, |
---|
1136 | | - unsigned long l_iova, size_t size) |
---|
| 1135 | + unsigned long l_iova, size_t size, |
---|
| 1136 | + struct iommu_iotlb_gather *gather) |
---|
1137 | 1137 | { |
---|
1138 | 1138 | struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain); |
---|
1139 | 1139 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; |
---|
.. | .. |
---|
1154 | 1154 | } |
---|
1155 | 1155 | |
---|
1156 | 1156 | /* workaround for h/w bug in System MMU v3.3 */ |
---|
1157 | | - update_pte(ent, ZERO_LV2LINK); |
---|
| 1157 | + exynos_iommu_set_pte(ent, ZERO_LV2LINK); |
---|
1158 | 1158 | size = SECT_SIZE; |
---|
1159 | 1159 | goto done; |
---|
1160 | 1160 | } |
---|
.. | .. |
---|
1175 | 1175 | } |
---|
1176 | 1176 | |
---|
1177 | 1177 | if (lv2ent_small(ent)) { |
---|
1178 | | - update_pte(ent, 0); |
---|
| 1178 | + exynos_iommu_set_pte(ent, 0); |
---|
1179 | 1179 | size = SPAGE_SIZE; |
---|
1180 | 1180 | domain->lv2entcnt[lv1ent_offset(iova)] += 1; |
---|
1181 | 1181 | goto done; |
---|
.. | .. |
---|
1239 | 1239 | return phys; |
---|
1240 | 1240 | } |
---|
1241 | 1241 | |
---|
1242 | | -static int exynos_iommu_add_device(struct device *dev) |
---|
| 1242 | +static struct iommu_device *exynos_iommu_probe_device(struct device *dev) |
---|
1243 | 1243 | { |
---|
1244 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
---|
| 1244 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
---|
1245 | 1245 | struct sysmmu_drvdata *data; |
---|
1246 | | - struct iommu_group *group; |
---|
1247 | 1246 | |
---|
1248 | 1247 | if (!has_sysmmu(dev)) |
---|
1249 | | - return -ENODEV; |
---|
1250 | | - |
---|
1251 | | - group = iommu_group_get_for_dev(dev); |
---|
1252 | | - |
---|
1253 | | - if (IS_ERR(group)) |
---|
1254 | | - return PTR_ERR(group); |
---|
| 1248 | + return ERR_PTR(-ENODEV); |
---|
1255 | 1249 | |
---|
1256 | 1250 | list_for_each_entry(data, &owner->controllers, owner_node) { |
---|
1257 | 1251 | /* |
---|
.. | .. |
---|
1263 | 1257 | DL_FLAG_STATELESS | |
---|
1264 | 1258 | DL_FLAG_PM_RUNTIME); |
---|
1265 | 1259 | } |
---|
1266 | | - iommu_group_put(group); |
---|
1267 | 1260 | |
---|
1268 | | - return 0; |
---|
| 1261 | + /* There is always at least one entry, see exynos_iommu_of_xlate() */ |
---|
| 1262 | + data = list_first_entry(&owner->controllers, |
---|
| 1263 | + struct sysmmu_drvdata, owner_node); |
---|
| 1264 | + |
---|
| 1265 | + return &data->iommu; |
---|
1269 | 1266 | } |
---|
1270 | 1267 | |
---|
1271 | | -static void exynos_iommu_remove_device(struct device *dev) |
---|
| 1268 | +static void exynos_iommu_release_device(struct device *dev) |
---|
1272 | 1269 | { |
---|
1273 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
---|
| 1270 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
---|
1274 | 1271 | struct sysmmu_drvdata *data; |
---|
1275 | 1272 | |
---|
1276 | 1273 | if (!has_sysmmu(dev)) |
---|
.. | .. |
---|
1286 | 1283 | iommu_group_put(group); |
---|
1287 | 1284 | } |
---|
1288 | 1285 | } |
---|
1289 | | - iommu_group_remove_device(dev); |
---|
1290 | 1286 | |
---|
1291 | 1287 | list_for_each_entry(data, &owner->controllers, owner_node) |
---|
1292 | 1288 | device_link_del(data->link); |
---|
.. | .. |
---|
1295 | 1291 | static int exynos_iommu_of_xlate(struct device *dev, |
---|
1296 | 1292 | struct of_phandle_args *spec) |
---|
1297 | 1293 | { |
---|
1298 | | - struct exynos_iommu_owner *owner = dev->archdata.iommu; |
---|
1299 | 1294 | struct platform_device *sysmmu = of_find_device_by_node(spec->np); |
---|
| 1295 | + struct exynos_iommu_owner *owner = dev_iommu_priv_get(dev); |
---|
1300 | 1296 | struct sysmmu_drvdata *data, *entry; |
---|
1301 | 1297 | |
---|
1302 | 1298 | if (!sysmmu) |
---|
.. | .. |
---|
1317 | 1313 | |
---|
1318 | 1314 | INIT_LIST_HEAD(&owner->controllers); |
---|
1319 | 1315 | mutex_init(&owner->rpm_lock); |
---|
1320 | | - dev->archdata.iommu = owner; |
---|
| 1316 | + dev_iommu_priv_set(dev, owner); |
---|
1321 | 1317 | } |
---|
1322 | 1318 | |
---|
1323 | 1319 | list_for_each_entry(entry, &owner->controllers, owner_node) |
---|
.. | .. |
---|
1339 | 1335 | .unmap = exynos_iommu_unmap, |
---|
1340 | 1336 | .iova_to_phys = exynos_iommu_iova_to_phys, |
---|
1341 | 1337 | .device_group = generic_device_group, |
---|
1342 | | - .add_device = exynos_iommu_add_device, |
---|
1343 | | - .remove_device = exynos_iommu_remove_device, |
---|
| 1338 | + .probe_device = exynos_iommu_probe_device, |
---|
| 1339 | + .release_device = exynos_iommu_release_device, |
---|
1344 | 1340 | .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, |
---|
1345 | 1341 | .of_xlate = exynos_iommu_of_xlate, |
---|
1346 | 1342 | }; |
---|