2022-05-25 02:18:06

by Nobuhiro Iwamatsu

[permalink] [raw]
Subject: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

Add IOMMU (ATU) driver can bse used for Visconti5's multimedia IPs, such as
DCNN (Deep Convolutional Neural Network), VIIF(Video Input), VOIF(Video
output), and others.

Signed-off-by: Nobuhiro Iwamatsu <[email protected]>
---
drivers/iommu/Kconfig | 7 +
drivers/iommu/Makefile | 1 +
drivers/iommu/visconti-atu.c | 426 +++++++++++++++++++++++++++++++++++
3 files changed, 434 insertions(+)
create mode 100644 drivers/iommu/visconti-atu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index c79a0df090c0..8a4351020b7f 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -486,4 +486,11 @@ config SPRD_IOMMU

Say Y here if you want to use the multimedia devices listed above.

+config VISCONTI_ATU
+ tristate "Toshiba Visconti5 IOMMU Support"
+ depends on ARCH_VISCONTI || COMPILE_TEST
+ select IOMMU_API
+ help
+ Support for the IOMMU API for Toshiba Visconti5 ARM SoCs.
+
endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 44475a9b3eea..077189f908ea 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o
obj-$(CONFIG_IOMMU_SVA) += iommu-sva-lib.o io-pgfault.o
obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
obj-$(CONFIG_APPLE_DART) += apple-dart.o
+obj-$(CONFIG_VISCONTI_ATU) += visconti-atu.o
diff --git a/drivers/iommu/visconti-atu.c b/drivers/iommu/visconti-atu.c
new file mode 100644
index 000000000000..269c912ad4c9
--- /dev/null
+++ b/drivers/iommu/visconti-atu.c
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Toshiba Visconti5 IOMMU (ATU) driver
+ *
+ * (C) Copyright 2022 Toshiba Electronic Devices & Storage Corporation
+ * (C) Copyright 2022 Toshiba CORPORATION
+ *
+ * Author: Nobuhiro Iwamatsu <[email protected]>
+ */
+
+#include <linux/dma-iommu.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+/* Regsiter address */
+#define ATU_AT_EN 0x0000
+#define ATU_AT_ENTRY_EN 0x0020
+
+#define ATU_AT_BLADDR 0x0030
+#define ATU_AT_ELADDR 0x0038
+#define ATU_AT_BGADDR0 0x0040
+#define ATU_AT_BGADDR1 0x0044
+#define ATU_AT_CONF 0x0048
+#define ATU_AT_REG(n, reg) (0x20 * n + reg)
+
+#define ATU_INT_START 0x0440
+#define ATU_INT_MASKED_STAT 0x0444
+#define ATU_INT_MASK 0x0448
+#define ATU_RP_CONF 0x0450
+#define ATU_ERR_ADDR 0x0454
+#define ATU_ERR_CLR 0x045C
+#define ATU_STAT 0x0460
+
+#define ATU_BGADDR_MASK GENMASK(31, 0)
+
+#define ATU_IOMMU_PGSIZE_BITMAP 0x7ffff000 /* SZ_1G - SZ_4K */
+#define ATU_MAX_IOMMU_ENTRY 32
+
+struct visconti_atu_device {
+ struct device *dev;
+ void __iomem *base;
+ struct iommu_device iommu;
+ struct iommu_group *group;
+
+ unsigned int num_entry;
+ unsigned int num_map_entry;
+ unsigned int enable_entry;
+ unsigned long iova[ATU_MAX_IOMMU_ENTRY];
+ phys_addr_t paddr[ATU_MAX_IOMMU_ENTRY];
+ size_t size[ATU_MAX_IOMMU_ENTRY];
+
+ spinlock_t lock;
+};
+
+struct visconti_atu_domain {
+ struct visconti_atu_device *atu;
+ struct iommu_domain io_domain;
+ struct mutex mutex;
+};
+
+static const struct iommu_ops visconti_atu_ops;
+
+static struct visconti_atu_domain *to_atu_domain(struct iommu_domain *domain)
+{
+ return container_of(domain, struct visconti_atu_domain, io_domain);
+}
+
+static inline void visconti_atu_write(struct visconti_atu_device *atu, u32 reg,
+ u32 val)
+{
+ writel_relaxed(val, atu->base + reg);
+}
+
+static inline u32 visconti_atu_read(struct visconti_atu_device *atu, u32 reg)
+{
+ return readl_relaxed(atu->base + reg);
+}
+
+static void visconti_atu_enable_entry(struct visconti_atu_device *atu,
+ int num)
+{
+ dev_dbg(atu->dev, "enable ATU: %d\n", atu->enable_entry);
+
+ visconti_atu_write(atu, ATU_AT_EN, 0);
+ if (atu->enable_entry & BIT(num)) {
+ visconti_atu_write(atu,
+ ATU_AT_REG(num, ATU_AT_BLADDR),
+ atu->iova[num]);
+ visconti_atu_write(atu,
+ ATU_AT_REG(num, ATU_AT_ELADDR),
+ atu->iova[num] + atu->size[num] - 1);
+ visconti_atu_write(atu,
+ ATU_AT_REG(num, ATU_AT_BGADDR0),
+ atu->iova[num] & ATU_BGADDR_MASK);
+ visconti_atu_write(atu,
+ ATU_AT_REG(num, ATU_AT_BGADDR1),
+ (atu->iova[num] >> 32) & ATU_BGADDR_MASK);
+ }
+ visconti_atu_write(atu, ATU_AT_ENTRY_EN, atu->enable_entry);
+ visconti_atu_write(atu, ATU_AT_EN, 1);
+}
+
+static void visconti_atu_disable_entry(struct visconti_atu_device *atu)
+{
+ dev_dbg(atu->dev, "disable ATU: %d\n", atu->enable_entry);
+
+ visconti_atu_write(atu, ATU_AT_EN, 0);
+ visconti_atu_write(atu, ATU_AT_ENTRY_EN, atu->enable_entry);
+ visconti_atu_write(atu, ATU_AT_EN, 1);
+}
+
+static int visconti_atu_attach_device(struct iommu_domain *io_domain,
+ struct device *dev)
+{
+ struct visconti_atu_domain *domain = to_atu_domain(io_domain);
+ struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
+ int ret = 0;
+
+ if (!atu) {
+ dev_err(dev, "Cannot attach to ATU\n");
+ return -ENXIO;
+ }
+
+ mutex_lock(&domain->mutex);
+
+ if (!domain->atu) {
+ domain->atu = atu;
+ } else if (domain->atu != atu) {
+ dev_err(dev, "Can't attach ATU %s to domain on ATU %s\n",
+ dev_name(atu->dev), dev_name(domain->atu->dev));
+ ret = -EINVAL;
+ } else {
+ dev_warn(dev, "Reusing ATU context\n");
+ }
+
+ mutex_unlock(&domain->mutex);
+
+ return ret;
+}
+
+static void visconti_atu_detach_device(struct iommu_domain *io_domain,
+ struct device *dev)
+{
+ struct visconti_atu_domain *domain = to_atu_domain(io_domain);
+ struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
+
+ if (domain->atu != atu)
+ return;
+
+ domain->atu = NULL;
+}
+
+static int visconti_atu_map(struct iommu_domain *io_domain,
+ unsigned long iova,
+ phys_addr_t paddr,
+ size_t size, int prot, gfp_t gfp)
+{
+ struct visconti_atu_domain *domain = to_atu_domain(io_domain);
+ struct visconti_atu_device *atu = domain->atu;
+ unsigned long flags;
+ unsigned int i;
+
+ if (!domain)
+ return -ENODEV;
+
+ spin_lock_irqsave(&atu->lock, flags);
+ for (i = 0; i < atu->num_map_entry; i++) {
+ if (!(atu->enable_entry & BIT(i))) {
+ atu->enable_entry |= BIT(i);
+ atu->iova[i] = iova;
+ atu->paddr[i] = paddr;
+ atu->size[i] = size;
+
+ visconti_atu_enable_entry(atu, i);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&atu->lock, flags);
+
+ if (i == atu->num_map_entry) {
+ dev_err(atu->dev, "map: not enough entry.\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static size_t visconti_atu_unmap(struct iommu_domain *io_domain,
+ unsigned long iova,
+ size_t size,
+ struct iommu_iotlb_gather *iotlb_gather)
+{
+ struct visconti_atu_domain *domain = to_atu_domain(io_domain);
+ struct visconti_atu_device *atu = domain->atu;
+ size_t tmp_size = size;
+ unsigned long flags;
+ unsigned int i;
+
+ spin_lock_irqsave(&atu->lock, flags);
+
+ while (tmp_size != 0) {
+ for (i = 0; i < atu->num_map_entry; i++) {
+ if (atu->iova[i] != iova)
+ continue;
+
+ atu->enable_entry &= ~BIT(i);
+ iova += atu->size[i];
+ tmp_size -= atu->size[i];
+
+ visconti_atu_disable_entry(atu);
+
+ break;
+ }
+ if (i == atu->num_map_entry) {
+ dev_err(atu->dev, "unmap: not found entry.\n");
+ size = 0;
+ goto out;
+ }
+ }
+
+ if (!atu->num_map_entry)
+ visconti_atu_write(atu, ATU_AT_EN, 0);
+out:
+ spin_unlock_irqrestore(&atu->lock, flags);
+ return size;
+}
+
+static phys_addr_t visconti_atu_iova_to_phys(struct iommu_domain *io_domain,
+ dma_addr_t iova)
+{
+ struct visconti_atu_domain *domain = to_atu_domain(io_domain);
+ struct visconti_atu_device *atu = domain->atu;
+ phys_addr_t paddr = 0;
+ unsigned int i;
+
+ for (i = 0; i < atu->num_map_entry; i++) {
+ if (!(atu->enable_entry & BIT(i)))
+ continue;
+ if (atu->iova[i] <= iova && iova < (atu->iova[i] + atu->size[i])) {
+ paddr = atu->paddr[i];
+ paddr += iova & (atu->size[i] - 1);
+ break;
+ }
+ }
+
+ dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
+
+ return paddr;
+}
+
+static int visconti_atu_of_xlate(struct device *dev, struct of_phandle_args *args)
+{
+ if (!dev_iommu_priv_get(dev)) {
+ struct platform_device *pdev;
+
+ pdev = of_find_device_by_node(args->np);
+ dev_iommu_priv_set(dev, platform_get_drvdata(pdev));
+ platform_device_put(pdev);
+ }
+
+ return 0;
+}
+
+static struct iommu_domain *visconti_atu_domain_alloc(unsigned int type)
+{
+ struct visconti_atu_domain *domain;
+
+ if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
+ return NULL;
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (!domain)
+ return NULL;
+
+ mutex_init(&domain->mutex);
+
+ domain->io_domain.geometry.aperture_start = 0;
+ domain->io_domain.geometry.aperture_end = DMA_BIT_MASK(32);
+ domain->io_domain.geometry.force_aperture = true;
+
+ return &domain->io_domain;
+}
+
+static void visconti_atu_domain_free(struct iommu_domain *io_domain)
+{
+ struct visconti_atu_domain *domain = to_atu_domain(io_domain);
+
+ kfree(domain);
+}
+
+static struct iommu_device *visconti_atu_probe_device(struct device *dev)
+{
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+ struct visconti_atu_device *atu;
+
+ if (!fwspec || fwspec->ops != &visconti_atu_ops)
+ return ERR_PTR(-ENODEV);
+
+ atu = dev_iommu_priv_get(dev);
+ return &atu->iommu;
+}
+
+static void visconti_atu_release_device(struct device *dev)
+{
+ struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
+
+ if (!atu)
+ return;
+
+ iommu_fwspec_free(dev);
+}
+
+static const struct iommu_ops visconti_atu_ops = {
+ .domain_alloc = visconti_atu_domain_alloc,
+ .probe_device = visconti_atu_probe_device,
+ .release_device = visconti_atu_release_device,
+ .device_group = generic_device_group,
+ .of_xlate = visconti_atu_of_xlate,
+ .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
+ .default_domain_ops = &(const struct iommu_domain_ops) {
+ .attach_dev = visconti_atu_attach_device,
+ .detach_dev = visconti_atu_detach_device,
+ .map = visconti_atu_map,
+ .unmap = visconti_atu_unmap,
+ .iova_to_phys = visconti_atu_iova_to_phys,
+ .free = visconti_atu_domain_free,
+ }
+};
+
+static int visconti_atu_probe(struct platform_device *pdev)
+{
+ struct visconti_atu_device *atu;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ u32 reserved_entry;
+ int ret;
+
+ atu = devm_kzalloc(&pdev->dev, sizeof(*atu), GFP_KERNEL);
+ if (!atu)
+ return -ENOMEM;
+
+ ret = of_property_read_u32(dev->of_node, "toshiba,max-entry",
+ &atu->num_entry);
+ if (ret < 0) {
+ dev_err(dev, "cannot get max-entry data\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "toshiba,reserved-entry",
+ &reserved_entry);
+ if (ret < 0)
+ reserved_entry = 0;
+
+ if (atu->num_entry < reserved_entry)
+ return -EINVAL;
+
+ atu->num_map_entry = atu->num_entry - reserved_entry;
+ atu->enable_entry = 0;
+ atu->dev = dev;
+
+ atu->group = iommu_group_alloc();
+ if (IS_ERR(atu->group)) {
+ ret = PTR_ERR(atu->group);
+ goto out;
+ }
+
+ spin_lock_init(&atu->lock);
+
+ atu->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(atu->base)) {
+ ret = PTR_ERR(atu->base);
+ goto out;
+ }
+
+ ret = iommu_device_sysfs_add(&atu->iommu, dev, NULL, dev_name(dev));
+ if (ret)
+ goto out;
+
+ ret = iommu_device_register(&atu->iommu, &visconti_atu_ops, dev);
+ if (ret)
+ goto remove_sysfs;
+
+ if (!iommu_present(&platform_bus_type))
+ bus_set_iommu(&platform_bus_type, &visconti_atu_ops);
+ platform_set_drvdata(pdev, atu);
+
+ return 0;
+
+remove_sysfs:
+ iommu_device_sysfs_remove(&atu->iommu);
+out:
+ return ret;
+}
+
+static int visconti_atu_remove(struct platform_device *pdev)
+{
+ struct visconti_atu_device *atu = platform_get_drvdata(pdev);
+
+ iommu_device_sysfs_remove(&atu->iommu);
+ iommu_device_unregister(&atu->iommu);
+
+ return 0;
+}
+
+static const struct of_device_id visconti_atu_of_match[] = {
+ { .compatible = "toshiba,visconti-atu", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, visconti_atu_of_match);
+
+static struct platform_driver visconti_atu_driver = {
+ .driver = {
+ .name = "visconti-atu",
+ .of_match_table = visconti_atu_of_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = visconti_atu_probe,
+ .remove = visconti_atu_remove,
+};
+
+builtin_platform_driver(visconti_atu_driver);
--
2.36.0




2022-05-25 05:48:44

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

Hi Nobuhiro,

I love your patch! Perhaps something to improve:

[auto build test WARNING on joro-iommu/next]
[also build test WARNING on arm-perf/for-next/perf soc/for-next linus/master v5.18 next-20220524]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326
base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: nios2-allyesconfig (https://download.01.org/0day-ci/archive/20220525/[email protected]/config)
compiler: nios2-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/69bb4f3c2ef0bb1f65922bc72bb31109897a6393
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326
git checkout 69bb4f3c2ef0bb1f65922bc72bb31109897a6393
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=nios2 SHELL=/bin/bash drivers/iommu/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

drivers/iommu/visconti-atu.c:47:29: error: field 'iommu' has incomplete type
47 | struct iommu_device iommu;
| ^~~~~
drivers/iommu/visconti-atu.c:62:29: error: field 'io_domain' has incomplete type
62 | struct iommu_domain io_domain;
| ^~~~~~~~~
In file included from include/linux/bits.h:22,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/iommu/visconti-atu.c:12:
drivers/iommu/visconti-atu.c: In function 'to_atu_domain':
include/linux/compiler_types.h:293:27: error: expression in static assertion is not an integer
293 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
drivers/iommu/visconti-atu.c:70:16: note: in expansion of macro 'container_of'
70 | return container_of(domain, struct visconti_atu_domain, io_domain);
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_enable_entry':
>> drivers/iommu/visconti-atu.c:102:52: warning: right shift count >= width of type [-Wshift-count-overflow]
102 | (atu->iova[num] >> 32) & ATU_BGADDR_MASK);
| ^~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_attach_device':
drivers/iommu/visconti-atu.c:121:43: error: implicit declaration of function 'dev_iommu_priv_get' [-Werror=implicit-function-declaration]
121 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:121:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
drivers/iommu/visconti-atu.c: In function 'visconti_atu_detach_device':
drivers/iommu/visconti-atu.c:150:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
150 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: At top level:
drivers/iommu/visconti-atu.c:196:41: warning: 'struct iommu_iotlb_gather' declared inside parameter list will not be visible outside of this definition or declaration
196 | struct iommu_iotlb_gather *iotlb_gather)
| ^~~~~~~~~~~~~~~~~~
In file included from include/linux/printk.h:555,
from include/asm-generic/bug.h:22,
from ./arch/nios2/include/generated/asm/bug.h:1,
from include/linux/bug.h:5,
from include/linux/thread_info.h:13,
from include/asm-generic/current.h:5,
from ./arch/nios2/include/generated/asm/current.h:1,
from include/linux/sched.h:12,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/iommu/visconti-atu.c:12:
drivers/iommu/visconti-atu.c: In function 'visconti_atu_iova_to_phys':
>> drivers/iommu/visconti-atu.c:251:27: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'dma_addr_t' {aka 'unsigned int'} [-Wformat=]
251 | dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/dynamic_debug.h:134:29: note: in definition of macro '__dynamic_func_call'
134 | func(&id, ##__VA_ARGS__); \
| ^~~~~~~~~~~
include/linux/dynamic_debug.h:166:9: note: in expansion of macro '_dynamic_func_call'
166 | _dynamic_func_call(fmt,__dynamic_dev_dbg, \
| ^~~~~~~~~~~~~~~~~~
include/linux/dev_printk.h:155:9: note: in expansion of macro 'dynamic_dev_dbg'
155 | dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~~~~~~~~~
include/linux/dev_printk.h:155:30: note: in expansion of macro 'dev_fmt'
155 | dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~
drivers/iommu/visconti-atu.c:251:9: note: in expansion of macro 'dev_dbg'
251 | dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
| ^~~~~~~
drivers/iommu/visconti-atu.c:251:45: note: format string is defined here
251 | dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
| ~~~^
| |
| long long unsigned int
| %x
In file included from include/linux/printk.h:555,
from include/asm-generic/bug.h:22,
from ./arch/nios2/include/generated/asm/bug.h:1,
from include/linux/bug.h:5,
from include/linux/thread_info.h:13,
from include/asm-generic/current.h:5,
from ./arch/nios2/include/generated/asm/current.h:1,
from include/linux/sched.h:12,
from include/linux/ratelimit.h:6,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/iommu/visconti-atu.c:12:
>> drivers/iommu/visconti-atu.c:251:27: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type 'phys_addr_t' {aka 'unsigned int'} [-Wformat=]
251 | dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/dynamic_debug.h:134:29: note: in definition of macro '__dynamic_func_call'
134 | func(&id, ##__VA_ARGS__); \
| ^~~~~~~~~~~
include/linux/dynamic_debug.h:166:9: note: in expansion of macro '_dynamic_func_call'
166 | _dynamic_func_call(fmt,__dynamic_dev_dbg, \
| ^~~~~~~~~~~~~~~~~~
include/linux/dev_printk.h:155:9: note: in expansion of macro 'dynamic_dev_dbg'
155 | dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~~~~~~~~~
include/linux/dev_printk.h:155:30: note: in expansion of macro 'dev_fmt'
155 | dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~
drivers/iommu/visconti-atu.c:251:9: note: in expansion of macro 'dev_dbg'
251 | dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
| ^~~~~~~
drivers/iommu/visconti-atu.c:251:53: note: format string is defined here
251 | dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
| ~~~^
| |
| long long unsigned int
| %x
drivers/iommu/visconti-atu.c: In function 'visconti_atu_of_xlate':
drivers/iommu/visconti-atu.c:262:17: error: implicit declaration of function 'dev_iommu_priv_set' [-Werror=implicit-function-declaration]
262 | dev_iommu_priv_set(dev, platform_get_drvdata(pdev));
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_domain_alloc':
drivers/iommu/visconti-atu.c:273:21: error: 'IOMMU_DOMAIN_UNMANAGED' undeclared (first use in this function)
273 | if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:273:21: note: each undeclared identifier is reported only once for each function it appears in
drivers/iommu/visconti-atu.c:273:55: error: 'IOMMU_DOMAIN_DMA' undeclared (first use in this function)
273 | if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_probe_device':
drivers/iommu/visconti-atu.c:298:39: error: implicit declaration of function 'dev_iommu_fwspec_get' [-Werror=implicit-function-declaration]
298 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
| ^~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:298:39: warning: initialization of 'struct iommu_fwspec *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
drivers/iommu/visconti-atu.c:301:30: error: invalid use of undefined type 'struct iommu_fwspec'
301 | if (!fwspec || fwspec->ops != &visconti_atu_ops)
| ^~
drivers/iommu/visconti-atu.c:304:13: warning: assignment to 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
304 | atu = dev_iommu_priv_get(dev);
| ^
drivers/iommu/visconti-atu.c: In function 'visconti_atu_release_device':
drivers/iommu/visconti-atu.c:310:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
310 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:315:9: error: implicit declaration of function 'iommu_fwspec_free' [-Werror=implicit-function-declaration]
315 | iommu_fwspec_free(dev);
| ^~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: At top level:
drivers/iommu/visconti-atu.c:318:21: error: variable 'visconti_atu_ops' has initializer but incomplete type
318 | static const struct iommu_ops visconti_atu_ops = {
| ^~~~~~~~~
drivers/iommu/visconti-atu.c:319:10: error: 'const struct iommu_ops' has no member named 'domain_alloc'
319 | .domain_alloc = visconti_atu_domain_alloc,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:319:25: warning: excess elements in struct initializer
319 | .domain_alloc = visconti_atu_domain_alloc,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:319:25: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:320:10: error: 'const struct iommu_ops' has no member named 'probe_device'
320 | .probe_device = visconti_atu_probe_device,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:320:25: warning: excess elements in struct initializer
320 | .probe_device = visconti_atu_probe_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:320:25: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:321:10: error: 'const struct iommu_ops' has no member named 'release_device'
321 | .release_device = visconti_atu_release_device,
| ^~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:321:27: warning: excess elements in struct initializer
321 | .release_device = visconti_atu_release_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:321:27: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:322:10: error: 'const struct iommu_ops' has no member named 'device_group'
322 | .device_group = generic_device_group,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:322:25: error: 'generic_device_group' undeclared here (not in a function)
322 | .device_group = generic_device_group,
| ^~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:322:25: warning: excess elements in struct initializer
drivers/iommu/visconti-atu.c:322:25: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:323:10: error: 'const struct iommu_ops' has no member named 'of_xlate'
323 | .of_xlate = visconti_atu_of_xlate,
| ^~~~~~~~
drivers/iommu/visconti-atu.c:323:21: warning: excess elements in struct initializer
323 | .of_xlate = visconti_atu_of_xlate,
| ^~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:323:21: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:324:10: error: 'const struct iommu_ops' has no member named 'pgsize_bitmap'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:41:33: warning: excess elements in struct initializer
41 | #define ATU_IOMMU_PGSIZE_BITMAP 0x7ffff000 /* SZ_1G - SZ_4K */
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:324:26: note: in expansion of macro 'ATU_IOMMU_PGSIZE_BITMAP'


vim +102 drivers/iommu/visconti-atu.c

83
84 static void visconti_atu_enable_entry(struct visconti_atu_device *atu,
85 int num)
86 {
87 dev_dbg(atu->dev, "enable ATU: %d\n", atu->enable_entry);
88
89 visconti_atu_write(atu, ATU_AT_EN, 0);
90 if (atu->enable_entry & BIT(num)) {
91 visconti_atu_write(atu,
92 ATU_AT_REG(num, ATU_AT_BLADDR),
93 atu->iova[num]);
94 visconti_atu_write(atu,
95 ATU_AT_REG(num, ATU_AT_ELADDR),
96 atu->iova[num] + atu->size[num] - 1);
97 visconti_atu_write(atu,
98 ATU_AT_REG(num, ATU_AT_BGADDR0),
99 atu->iova[num] & ATU_BGADDR_MASK);
100 visconti_atu_write(atu,
101 ATU_AT_REG(num, ATU_AT_BGADDR1),
> 102 (atu->iova[num] >> 32) & ATU_BGADDR_MASK);
103 }
104 visconti_atu_write(atu, ATU_AT_ENTRY_EN, atu->enable_entry);
105 visconti_atu_write(atu, ATU_AT_EN, 1);
106 }
107
108 static void visconti_atu_disable_entry(struct visconti_atu_device *atu)
109 {
110 dev_dbg(atu->dev, "disable ATU: %d\n", atu->enable_entry);
111
112 visconti_atu_write(atu, ATU_AT_EN, 0);
113 visconti_atu_write(atu, ATU_AT_ENTRY_EN, atu->enable_entry);
114 visconti_atu_write(atu, ATU_AT_EN, 1);
115 }
116
117 static int visconti_atu_attach_device(struct iommu_domain *io_domain,
118 struct device *dev)
119 {
120 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
121 struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
122 int ret = 0;
123
124 if (!atu) {
125 dev_err(dev, "Cannot attach to ATU\n");
126 return -ENXIO;
127 }
128
129 mutex_lock(&domain->mutex);
130
131 if (!domain->atu) {
132 domain->atu = atu;
133 } else if (domain->atu != atu) {
134 dev_err(dev, "Can't attach ATU %s to domain on ATU %s\n",
135 dev_name(atu->dev), dev_name(domain->atu->dev));
136 ret = -EINVAL;
137 } else {
138 dev_warn(dev, "Reusing ATU context\n");
139 }
140
141 mutex_unlock(&domain->mutex);
142
143 return ret;
144 }
145
146 static void visconti_atu_detach_device(struct iommu_domain *io_domain,
147 struct device *dev)
148 {
149 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
150 struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
151
152 if (domain->atu != atu)
153 return;
154
155 domain->atu = NULL;
156 }
157
158 static int visconti_atu_map(struct iommu_domain *io_domain,
159 unsigned long iova,
160 phys_addr_t paddr,
161 size_t size, int prot, gfp_t gfp)
162 {
163 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
164 struct visconti_atu_device *atu = domain->atu;
165 unsigned long flags;
166 unsigned int i;
167
168 if (!domain)
169 return -ENODEV;
170
171 spin_lock_irqsave(&atu->lock, flags);
172 for (i = 0; i < atu->num_map_entry; i++) {
173 if (!(atu->enable_entry & BIT(i))) {
174 atu->enable_entry |= BIT(i);
175 atu->iova[i] = iova;
176 atu->paddr[i] = paddr;
177 atu->size[i] = size;
178
179 visconti_atu_enable_entry(atu, i);
180 break;
181 }
182 }
183 spin_unlock_irqrestore(&atu->lock, flags);
184
185 if (i == atu->num_map_entry) {
186 dev_err(atu->dev, "map: not enough entry.\n");
187 return -ENOMEM;
188 }
189
190 return 0;
191 }
192
193 static size_t visconti_atu_unmap(struct iommu_domain *io_domain,
194 unsigned long iova,
195 size_t size,
196 struct iommu_iotlb_gather *iotlb_gather)
197 {
198 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
199 struct visconti_atu_device *atu = domain->atu;
200 size_t tmp_size = size;
201 unsigned long flags;
202 unsigned int i;
203
204 spin_lock_irqsave(&atu->lock, flags);
205
206 while (tmp_size != 0) {
207 for (i = 0; i < atu->num_map_entry; i++) {
208 if (atu->iova[i] != iova)
209 continue;
210
211 atu->enable_entry &= ~BIT(i);
212 iova += atu->size[i];
213 tmp_size -= atu->size[i];
214
215 visconti_atu_disable_entry(atu);
216
217 break;
218 }
219 if (i == atu->num_map_entry) {
220 dev_err(atu->dev, "unmap: not found entry.\n");
221 size = 0;
222 goto out;
223 }
224 }
225
226 if (!atu->num_map_entry)
227 visconti_atu_write(atu, ATU_AT_EN, 0);
228 out:
229 spin_unlock_irqrestore(&atu->lock, flags);
230 return size;
231 }
232
233 static phys_addr_t visconti_atu_iova_to_phys(struct iommu_domain *io_domain,
234 dma_addr_t iova)
235 {
236 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
237 struct visconti_atu_device *atu = domain->atu;
238 phys_addr_t paddr = 0;
239 unsigned int i;
240
241 for (i = 0; i < atu->num_map_entry; i++) {
242 if (!(atu->enable_entry & BIT(i)))
243 continue;
244 if (atu->iova[i] <= iova && iova < (atu->iova[i] + atu->size[i])) {
245 paddr = atu->paddr[i];
246 paddr += iova & (atu->size[i] - 1);
247 break;
248 }
249 }
250
> 251 dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
252
253 return paddr;
254 }
255

--
0-DAY CI Kernel Test Service
https://01.org/lkp

2022-05-25 11:57:14

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

Hi Nobuhiro,

I love your patch! Perhaps something to improve:

[auto build test WARNING on joro-iommu/next]
[also build test WARNING on arm-perf/for-next/perf soc/for-next linus/master v5.18 next-20220524]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326
base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20220525/[email protected]/config)
compiler: alpha-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/69bb4f3c2ef0bb1f65922bc72bb31109897a6393
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326
git checkout 69bb4f3c2ef0bb1f65922bc72bb31109897a6393
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=alpha SHELL=/bin/bash drivers/iommu/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

drivers/iommu/visconti-atu.c:47:29: error: field 'iommu' has incomplete type
47 | struct iommu_device iommu;
| ^~~~~
drivers/iommu/visconti-atu.c:62:29: error: field 'io_domain' has incomplete type
62 | struct iommu_domain io_domain;
| ^~~~~~~~~
In file included from include/linux/bits.h:22,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/iommu/visconti-atu.c:12:
drivers/iommu/visconti-atu.c: In function 'to_atu_domain':
include/linux/compiler_types.h:293:27: error: expression in static assertion is not an integer
293 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
drivers/iommu/visconti-atu.c:70:16: note: in expansion of macro 'container_of'
70 | return container_of(domain, struct visconti_atu_domain, io_domain);
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_attach_device':
drivers/iommu/visconti-atu.c:121:43: error: implicit declaration of function 'dev_iommu_priv_get' [-Werror=implicit-function-declaration]
121 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:121:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
drivers/iommu/visconti-atu.c: In function 'visconti_atu_detach_device':
drivers/iommu/visconti-atu.c:150:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
150 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: At top level:
>> drivers/iommu/visconti-atu.c:196:41: warning: 'struct iommu_iotlb_gather' declared inside parameter list will not be visible outside of this definition or declaration
196 | struct iommu_iotlb_gather *iotlb_gather)
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_of_xlate':
drivers/iommu/visconti-atu.c:262:17: error: implicit declaration of function 'dev_iommu_priv_set' [-Werror=implicit-function-declaration]
262 | dev_iommu_priv_set(dev, platform_get_drvdata(pdev));
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_domain_alloc':
drivers/iommu/visconti-atu.c:273:21: error: 'IOMMU_DOMAIN_UNMANAGED' undeclared (first use in this function)
273 | if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:273:21: note: each undeclared identifier is reported only once for each function it appears in
drivers/iommu/visconti-atu.c:273:55: error: 'IOMMU_DOMAIN_DMA' undeclared (first use in this function)
273 | if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_probe_device':
drivers/iommu/visconti-atu.c:298:39: error: implicit declaration of function 'dev_iommu_fwspec_get' [-Werror=implicit-function-declaration]
298 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
| ^~~~~~~~~~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:298:39: warning: initialization of 'struct iommu_fwspec *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
drivers/iommu/visconti-atu.c:301:30: error: invalid use of undefined type 'struct iommu_fwspec'
301 | if (!fwspec || fwspec->ops != &visconti_atu_ops)
| ^~
>> drivers/iommu/visconti-atu.c:304:13: warning: assignment to 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
304 | atu = dev_iommu_priv_get(dev);
| ^
drivers/iommu/visconti-atu.c: In function 'visconti_atu_release_device':
drivers/iommu/visconti-atu.c:310:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
310 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:315:9: error: implicit declaration of function 'iommu_fwspec_free' [-Werror=implicit-function-declaration]
315 | iommu_fwspec_free(dev);
| ^~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: At top level:
drivers/iommu/visconti-atu.c:318:21: error: variable 'visconti_atu_ops' has initializer but incomplete type
318 | static const struct iommu_ops visconti_atu_ops = {
| ^~~~~~~~~
drivers/iommu/visconti-atu.c:319:10: error: 'const struct iommu_ops' has no member named 'domain_alloc'
319 | .domain_alloc = visconti_atu_domain_alloc,
| ^~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:319:25: warning: excess elements in struct initializer
319 | .domain_alloc = visconti_atu_domain_alloc,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:319:25: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:320:10: error: 'const struct iommu_ops' has no member named 'probe_device'
320 | .probe_device = visconti_atu_probe_device,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:320:25: warning: excess elements in struct initializer
320 | .probe_device = visconti_atu_probe_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:320:25: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:321:10: error: 'const struct iommu_ops' has no member named 'release_device'
321 | .release_device = visconti_atu_release_device,
| ^~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:321:27: warning: excess elements in struct initializer
321 | .release_device = visconti_atu_release_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:321:27: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:322:10: error: 'const struct iommu_ops' has no member named 'device_group'
322 | .device_group = generic_device_group,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:322:25: error: 'generic_device_group' undeclared here (not in a function)
322 | .device_group = generic_device_group,
| ^~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:322:25: warning: excess elements in struct initializer
drivers/iommu/visconti-atu.c:322:25: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:323:10: error: 'const struct iommu_ops' has no member named 'of_xlate'
323 | .of_xlate = visconti_atu_of_xlate,
| ^~~~~~~~
drivers/iommu/visconti-atu.c:323:21: warning: excess elements in struct initializer
323 | .of_xlate = visconti_atu_of_xlate,
| ^~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:323:21: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c:324:10: error: 'const struct iommu_ops' has no member named 'pgsize_bitmap'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:41:33: warning: excess elements in struct initializer
41 | #define ATU_IOMMU_PGSIZE_BITMAP 0x7ffff000 /* SZ_1G - SZ_4K */
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:324:26: note: in expansion of macro 'ATU_IOMMU_PGSIZE_BITMAP'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:41:33: note: (near initialization for 'visconti_atu_ops')
41 | #define ATU_IOMMU_PGSIZE_BITMAP 0x7ffff000 /* SZ_1G - SZ_4K */
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:324:26: note: in expansion of macro 'ATU_IOMMU_PGSIZE_BITMAP'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:325:10: error: 'const struct iommu_ops' has no member named 'default_domain_ops'
325 | .default_domain_ops = &(const struct iommu_domain_ops) {
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:326:18: error: 'const struct iommu_domain_ops' has no member named 'attach_dev'
326 | .attach_dev = visconti_atu_attach_device,
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:326:31: warning: excess elements in struct initializer
326 | .attach_dev = visconti_atu_attach_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:326:31: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:327:18: error: 'const struct iommu_domain_ops' has no member named 'detach_dev'
327 | .detach_dev = visconti_atu_detach_device,
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:327:31: warning: excess elements in struct initializer
327 | .detach_dev = visconti_atu_detach_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:327:31: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:328:18: error: 'const struct iommu_domain_ops' has no member named 'map'
328 | .map = visconti_atu_map,
| ^~~
drivers/iommu/visconti-atu.c:328:24: warning: excess elements in struct initializer
328 | .map = visconti_atu_map,
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:328:24: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:329:18: error: 'const struct iommu_domain_ops' has no member named 'unmap'
329 | .unmap = visconti_atu_unmap,
| ^~~~~
drivers/iommu/visconti-atu.c:329:26: warning: excess elements in struct initializer
329 | .unmap = visconti_atu_unmap,
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:329:26: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:330:18: error: 'const struct iommu_domain_ops' has no member named 'iova_to_phys'
330 | .iova_to_phys = visconti_atu_iova_to_phys,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:330:33: warning: excess elements in struct initializer
330 | .iova_to_phys = visconti_atu_iova_to_phys,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:330:33: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:331:18: error: 'const struct iommu_domain_ops' has no member named 'free'
331 | .free = visconti_atu_domain_free,
| ^~~~
drivers/iommu/visconti-atu.c:331:25: warning: excess elements in struct initializer
331 | .free = visconti_atu_domain_free,
| ^~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:331:25: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:325:64: error: invalid use of undefined type 'const struct iommu_domain_ops'
325 | .default_domain_ops = &(const struct iommu_domain_ops) {
| ^
drivers/iommu/visconti-atu.c:325:31: warning: excess elements in struct initializer
325 | .default_domain_ops = &(const struct iommu_domain_ops) {
| ^
drivers/iommu/visconti-atu.c:325:31: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c: In function 'visconti_atu_probe':
drivers/iommu/visconti-atu.c:366:22: error: implicit declaration of function 'iommu_group_alloc' [-Werror=implicit-function-declaration]
366 | atu->group = iommu_group_alloc();
| ^~~~~~~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:366:20: warning: assignment to 'struct iommu_group *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
366 | atu->group = iommu_group_alloc();
| ^
drivers/iommu/visconti-atu.c:380:15: error: implicit declaration of function 'iommu_device_sysfs_add' [-Werror=implicit-function-declaration]
380 | ret = iommu_device_sysfs_add(&atu->iommu, dev, NULL, dev_name(dev));
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:384:15: error: implicit declaration of function 'iommu_device_register'; did you mean 'of_device_register'? [-Werror=implicit-function-declaration]
384 | ret = iommu_device_register(&atu->iommu, &visconti_atu_ops, dev);
| ^~~~~~~~~~~~~~~~~~~~~
| of_device_register
drivers/iommu/visconti-atu.c:388:14: error: implicit declaration of function 'iommu_present'; did you mean 'pmd_present'? [-Werror=implicit-function-declaration]
388 | if (!iommu_present(&platform_bus_type))
| ^~~~~~~~~~~~~
| pmd_present
drivers/iommu/visconti-atu.c:389:17: error: implicit declaration of function 'bus_set_iommu' [-Werror=implicit-function-declaration]
389 | bus_set_iommu(&platform_bus_type, &visconti_atu_ops);
| ^~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:395:9: error: implicit declaration of function 'iommu_device_sysfs_remove' [-Werror=implicit-function-declaration]
395 | iommu_device_sysfs_remove(&atu->iommu);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_remove':
drivers/iommu/visconti-atu.c:405:9: error: implicit declaration of function 'iommu_device_unregister'; did you mean 'of_device_unregister'? [-Werror=implicit-function-declaration]
405 | iommu_device_unregister(&atu->iommu);
| ^~~~~~~~~~~~~~~~~~~~~~~
| of_device_unregister
drivers/iommu/visconti-atu.c: At top level:
drivers/iommu/visconti-atu.c:318:31: error: storage size of 'visconti_atu_ops' isn't known
318 | static const struct iommu_ops visconti_atu_ops = {
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:318:31: error: storage size of 'visconti_atu_ops' isn't known
cc1: some warnings being treated as errors


vim +121 drivers/iommu/visconti-atu.c

116
117 static int visconti_atu_attach_device(struct iommu_domain *io_domain,
118 struct device *dev)
119 {
120 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
> 121 struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
122 int ret = 0;
123
124 if (!atu) {
125 dev_err(dev, "Cannot attach to ATU\n");
126 return -ENXIO;
127 }
128
129 mutex_lock(&domain->mutex);
130
131 if (!domain->atu) {
132 domain->atu = atu;
133 } else if (domain->atu != atu) {
134 dev_err(dev, "Can't attach ATU %s to domain on ATU %s\n",
135 dev_name(atu->dev), dev_name(domain->atu->dev));
136 ret = -EINVAL;
137 } else {
138 dev_warn(dev, "Reusing ATU context\n");
139 }
140
141 mutex_unlock(&domain->mutex);
142
143 return ret;
144 }
145
146 static void visconti_atu_detach_device(struct iommu_domain *io_domain,
147 struct device *dev)
148 {
149 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
150 struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
151
152 if (domain->atu != atu)
153 return;
154
155 domain->atu = NULL;
156 }
157
158 static int visconti_atu_map(struct iommu_domain *io_domain,
159 unsigned long iova,
160 phys_addr_t paddr,
161 size_t size, int prot, gfp_t gfp)
162 {
163 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
164 struct visconti_atu_device *atu = domain->atu;
165 unsigned long flags;
166 unsigned int i;
167
168 if (!domain)
169 return -ENODEV;
170
171 spin_lock_irqsave(&atu->lock, flags);
172 for (i = 0; i < atu->num_map_entry; i++) {
173 if (!(atu->enable_entry & BIT(i))) {
174 atu->enable_entry |= BIT(i);
175 atu->iova[i] = iova;
176 atu->paddr[i] = paddr;
177 atu->size[i] = size;
178
179 visconti_atu_enable_entry(atu, i);
180 break;
181 }
182 }
183 spin_unlock_irqrestore(&atu->lock, flags);
184
185 if (i == atu->num_map_entry) {
186 dev_err(atu->dev, "map: not enough entry.\n");
187 return -ENOMEM;
188 }
189
190 return 0;
191 }
192
193 static size_t visconti_atu_unmap(struct iommu_domain *io_domain,
194 unsigned long iova,
195 size_t size,
> 196 struct iommu_iotlb_gather *iotlb_gather)
197 {
198 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
199 struct visconti_atu_device *atu = domain->atu;
200 size_t tmp_size = size;
201 unsigned long flags;
202 unsigned int i;
203
204 spin_lock_irqsave(&atu->lock, flags);
205
206 while (tmp_size != 0) {
207 for (i = 0; i < atu->num_map_entry; i++) {
208 if (atu->iova[i] != iova)
209 continue;
210
211 atu->enable_entry &= ~BIT(i);
212 iova += atu->size[i];
213 tmp_size -= atu->size[i];
214
215 visconti_atu_disable_entry(atu);
216
217 break;
218 }
219 if (i == atu->num_map_entry) {
220 dev_err(atu->dev, "unmap: not found entry.\n");
221 size = 0;
222 goto out;
223 }
224 }
225
226 if (!atu->num_map_entry)
227 visconti_atu_write(atu, ATU_AT_EN, 0);
228 out:
229 spin_unlock_irqrestore(&atu->lock, flags);
230 return size;
231 }
232
233 static phys_addr_t visconti_atu_iova_to_phys(struct iommu_domain *io_domain,
234 dma_addr_t iova)
235 {
236 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
237 struct visconti_atu_device *atu = domain->atu;
238 phys_addr_t paddr = 0;
239 unsigned int i;
240
241 for (i = 0; i < atu->num_map_entry; i++) {
242 if (!(atu->enable_entry & BIT(i)))
243 continue;
244 if (atu->iova[i] <= iova && iova < (atu->iova[i] + atu->size[i])) {
245 paddr = atu->paddr[i];
246 paddr += iova & (atu->size[i] - 1);
247 break;
248 }
249 }
250
251 dev_dbg(atu->dev, "iova_to_phys: %llx -> %llx\n", iova, paddr);
252
253 return paddr;
254 }
255
256 static int visconti_atu_of_xlate(struct device *dev, struct of_phandle_args *args)
257 {
258 if (!dev_iommu_priv_get(dev)) {
259 struct platform_device *pdev;
260
261 pdev = of_find_device_by_node(args->np);
262 dev_iommu_priv_set(dev, platform_get_drvdata(pdev));
263 platform_device_put(pdev);
264 }
265
266 return 0;
267 }
268
269 static struct iommu_domain *visconti_atu_domain_alloc(unsigned int type)
270 {
271 struct visconti_atu_domain *domain;
272
273 if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
274 return NULL;
275
276 domain = kzalloc(sizeof(*domain), GFP_KERNEL);
277 if (!domain)
278 return NULL;
279
280 mutex_init(&domain->mutex);
281
282 domain->io_domain.geometry.aperture_start = 0;
283 domain->io_domain.geometry.aperture_end = DMA_BIT_MASK(32);
284 domain->io_domain.geometry.force_aperture = true;
285
286 return &domain->io_domain;
287 }
288
289 static void visconti_atu_domain_free(struct iommu_domain *io_domain)
290 {
291 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
292
293 kfree(domain);
294 }
295
296 static struct iommu_device *visconti_atu_probe_device(struct device *dev)
297 {
> 298 struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
299 struct visconti_atu_device *atu;
300
301 if (!fwspec || fwspec->ops != &visconti_atu_ops)
302 return ERR_PTR(-ENODEV);
303
> 304 atu = dev_iommu_priv_get(dev);
305 return &atu->iommu;
306 }
307
308 static void visconti_atu_release_device(struct device *dev)
309 {
310 struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
311
312 if (!atu)
313 return;
314
315 iommu_fwspec_free(dev);
316 }
317
318 static const struct iommu_ops visconti_atu_ops = {
> 319 .domain_alloc = visconti_atu_domain_alloc,
320 .probe_device = visconti_atu_probe_device,
321 .release_device = visconti_atu_release_device,
322 .device_group = generic_device_group,
323 .of_xlate = visconti_atu_of_xlate,
324 .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
325 .default_domain_ops = &(const struct iommu_domain_ops) {
326 .attach_dev = visconti_atu_attach_device,
327 .detach_dev = visconti_atu_detach_device,
328 .map = visconti_atu_map,
329 .unmap = visconti_atu_unmap,
330 .iova_to_phys = visconti_atu_iova_to_phys,
331 .free = visconti_atu_domain_free,
332 }
333 };
334

--
0-DAY CI Kernel Test Service
https://01.org/lkp

2022-05-25 13:52:28

by Lu Baolu

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

On 2022/5/25 09:31, Nobuhiro Iwamatsu wrote:
> +static const struct iommu_ops visconti_atu_ops = {
> + .domain_alloc = visconti_atu_domain_alloc,
> + .probe_device = visconti_atu_probe_device,
> + .release_device = visconti_atu_release_device,
> + .device_group = generic_device_group,
> + .of_xlate = visconti_atu_of_xlate,
> + .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
> + .default_domain_ops = &(const struct iommu_domain_ops) {
> + .attach_dev = visconti_atu_attach_device,
> + .detach_dev = visconti_atu_detach_device,

The detach_dev callback is about to be deprecated. The new drivers
should implement the default domain and blocking domain instead.

> + .map = visconti_atu_map,
> + .unmap = visconti_atu_unmap,
> + .iova_to_phys = visconti_atu_iova_to_phys,
> + .free = visconti_atu_domain_free,
> + }
> +};

Best regards,
baolu

2022-05-26 11:45:05

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

On Wed, May 25, 2022 at 02:26:37PM +0800, Baolu Lu wrote:
> On 2022/5/25 09:31, Nobuhiro Iwamatsu wrote:
> > +static const struct iommu_ops visconti_atu_ops = {
> > + .domain_alloc = visconti_atu_domain_alloc,
> > + .probe_device = visconti_atu_probe_device,
> > + .release_device = visconti_atu_release_device,
> > + .device_group = generic_device_group,
> > + .of_xlate = visconti_atu_of_xlate,
> > + .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
> > + .default_domain_ops = &(const struct iommu_domain_ops) {
> > + .attach_dev = visconti_atu_attach_device,
> > + .detach_dev = visconti_atu_detach_device,
>
> The detach_dev callback is about to be deprecated. The new drivers
> should implement the default domain and blocking domain instead.

Yes please, new drivers need to use default_domains.

It is very strange that visconti_atu_detach_device() does nothing. It
is not required that a domain is fully unmapped before being
destructed, I think detach should set ATU_AT_EN to 0.

What behavior does the HW have when ATU_AT_ENTRY_EN == 0? If DMA is
rejected then this driver should have a IOMMU_DOMAIN_BLOCKING and
return that from ops->def_domain_type().

Attaching a the blocking domain should set ATU_AT_ENTRY_EN = 0

Also, if I surmise how this works properly, it is not following the
iommu API to halt all DMA during map/unmap operations. Should at least
document this and explain why it is OK..

I'm feeling like these "special" drivers need some kind of handshake
with their only users because they don't work with things like VFIO..

Jason

2022-05-27 09:09:21

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

Hi Nobuhiro,

I love your patch! Yet something to improve:

[auto build test ERROR on joro-iommu/next]
[also build test ERROR on arm-perf/for-next/perf soc/for-next linus/master v5.18 next-20220524]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326
base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20220525/[email protected]/config)
compiler: alpha-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/69bb4f3c2ef0bb1f65922bc72bb31109897a6393
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326
git checkout 69bb4f3c2ef0bb1f65922bc72bb31109897a6393
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 O=build_dir ARCH=alpha SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

Note: the linux-review/Nobuhiro-Iwamatsu/Add-Visconti5-IOMMU-driver/20220525-093326 HEAD 07739c72b066c0781c371eec7614ed876441e8dd builds fine.
It only hurts bisectability.

All errors (new ones prefixed by >>):

>> drivers/iommu/visconti-atu.c:47:29: error: field 'iommu' has incomplete type
47 | struct iommu_device iommu;
| ^~~~~
>> drivers/iommu/visconti-atu.c:62:29: error: field 'io_domain' has incomplete type
62 | struct iommu_domain io_domain;
| ^~~~~~~~~
In file included from include/linux/bits.h:22,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/iommu/visconti-atu.c:12:
drivers/iommu/visconti-atu.c: In function 'to_atu_domain':
include/linux/compiler_types.h:293:27: error: expression in static assertion is not an integer
293 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
drivers/iommu/visconti-atu.c:70:16: note: in expansion of macro 'container_of'
70 | return container_of(domain, struct visconti_atu_domain, io_domain);
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_attach_device':
>> drivers/iommu/visconti-atu.c:121:43: error: implicit declaration of function 'dev_iommu_priv_get' [-Werror=implicit-function-declaration]
121 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:121:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
drivers/iommu/visconti-atu.c: In function 'visconti_atu_detach_device':
drivers/iommu/visconti-atu.c:150:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
150 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: At top level:
drivers/iommu/visconti-atu.c:196:41: warning: 'struct iommu_iotlb_gather' declared inside parameter list will not be visible outside of this definition or declaration
196 | struct iommu_iotlb_gather *iotlb_gather)
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_of_xlate':
>> drivers/iommu/visconti-atu.c:262:17: error: implicit declaration of function 'dev_iommu_priv_set' [-Werror=implicit-function-declaration]
262 | dev_iommu_priv_set(dev, platform_get_drvdata(pdev));
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_domain_alloc':
>> drivers/iommu/visconti-atu.c:273:21: error: 'IOMMU_DOMAIN_UNMANAGED' undeclared (first use in this function)
273 | if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:273:21: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/iommu/visconti-atu.c:273:55: error: 'IOMMU_DOMAIN_DMA' undeclared (first use in this function)
273 | if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_probe_device':
>> drivers/iommu/visconti-atu.c:298:39: error: implicit declaration of function 'dev_iommu_fwspec_get' [-Werror=implicit-function-declaration]
298 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
| ^~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:298:39: warning: initialization of 'struct iommu_fwspec *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
>> drivers/iommu/visconti-atu.c:301:30: error: invalid use of undefined type 'struct iommu_fwspec'
301 | if (!fwspec || fwspec->ops != &visconti_atu_ops)
| ^~
drivers/iommu/visconti-atu.c:304:13: warning: assignment to 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
304 | atu = dev_iommu_priv_get(dev);
| ^
drivers/iommu/visconti-atu.c: In function 'visconti_atu_release_device':
drivers/iommu/visconti-atu.c:310:43: warning: initialization of 'struct visconti_atu_device *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
310 | struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
| ^~~~~~~~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:315:9: error: implicit declaration of function 'iommu_fwspec_free' [-Werror=implicit-function-declaration]
315 | iommu_fwspec_free(dev);
| ^~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: At top level:
>> drivers/iommu/visconti-atu.c:318:21: error: variable 'visconti_atu_ops' has initializer but incomplete type
318 | static const struct iommu_ops visconti_atu_ops = {
| ^~~~~~~~~
>> drivers/iommu/visconti-atu.c:319:10: error: 'const struct iommu_ops' has no member named 'domain_alloc'
319 | .domain_alloc = visconti_atu_domain_alloc,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:319:25: warning: excess elements in struct initializer
319 | .domain_alloc = visconti_atu_domain_alloc,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:319:25: note: (near initialization for 'visconti_atu_ops')
>> drivers/iommu/visconti-atu.c:320:10: error: 'const struct iommu_ops' has no member named 'probe_device'
320 | .probe_device = visconti_atu_probe_device,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:320:25: warning: excess elements in struct initializer
320 | .probe_device = visconti_atu_probe_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:320:25: note: (near initialization for 'visconti_atu_ops')
>> drivers/iommu/visconti-atu.c:321:10: error: 'const struct iommu_ops' has no member named 'release_device'
321 | .release_device = visconti_atu_release_device,
| ^~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:321:27: warning: excess elements in struct initializer
321 | .release_device = visconti_atu_release_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:321:27: note: (near initialization for 'visconti_atu_ops')
>> drivers/iommu/visconti-atu.c:322:10: error: 'const struct iommu_ops' has no member named 'device_group'
322 | .device_group = generic_device_group,
| ^~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:322:25: error: 'generic_device_group' undeclared here (not in a function)
322 | .device_group = generic_device_group,
| ^~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:322:25: warning: excess elements in struct initializer
drivers/iommu/visconti-atu.c:322:25: note: (near initialization for 'visconti_atu_ops')
>> drivers/iommu/visconti-atu.c:323:10: error: 'const struct iommu_ops' has no member named 'of_xlate'
323 | .of_xlate = visconti_atu_of_xlate,
| ^~~~~~~~
drivers/iommu/visconti-atu.c:323:21: warning: excess elements in struct initializer
323 | .of_xlate = visconti_atu_of_xlate,
| ^~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:323:21: note: (near initialization for 'visconti_atu_ops')
>> drivers/iommu/visconti-atu.c:324:10: error: 'const struct iommu_ops' has no member named 'pgsize_bitmap'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:41:33: warning: excess elements in struct initializer
41 | #define ATU_IOMMU_PGSIZE_BITMAP 0x7ffff000 /* SZ_1G - SZ_4K */
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:324:26: note: in expansion of macro 'ATU_IOMMU_PGSIZE_BITMAP'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:41:33: note: (near initialization for 'visconti_atu_ops')
41 | #define ATU_IOMMU_PGSIZE_BITMAP 0x7ffff000 /* SZ_1G - SZ_4K */
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:324:26: note: in expansion of macro 'ATU_IOMMU_PGSIZE_BITMAP'
324 | .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
| ^~~~~~~~~~~~~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:325:10: error: 'const struct iommu_ops' has no member named 'default_domain_ops'
325 | .default_domain_ops = &(const struct iommu_domain_ops) {
| ^~~~~~~~~~~~~~~~~~
>> drivers/iommu/visconti-atu.c:326:18: error: 'const struct iommu_domain_ops' has no member named 'attach_dev'
326 | .attach_dev = visconti_atu_attach_device,
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:326:31: warning: excess elements in struct initializer
326 | .attach_dev = visconti_atu_attach_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:326:31: note: (near initialization for '(anonymous)')
>> drivers/iommu/visconti-atu.c:327:18: error: 'const struct iommu_domain_ops' has no member named 'detach_dev'
327 | .detach_dev = visconti_atu_detach_device,
| ^~~~~~~~~~
drivers/iommu/visconti-atu.c:327:31: warning: excess elements in struct initializer
327 | .detach_dev = visconti_atu_detach_device,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:327:31: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:328:18: error: 'const struct iommu_domain_ops' has no member named 'map'
328 | .map = visconti_atu_map,
| ^~~
drivers/iommu/visconti-atu.c:328:24: warning: excess elements in struct initializer
328 | .map = visconti_atu_map,
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:328:24: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:329:18: error: 'const struct iommu_domain_ops' has no member named 'unmap'
329 | .unmap = visconti_atu_unmap,
| ^~~~~
drivers/iommu/visconti-atu.c:329:26: warning: excess elements in struct initializer
329 | .unmap = visconti_atu_unmap,
| ^~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:329:26: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:330:18: error: 'const struct iommu_domain_ops' has no member named 'iova_to_phys'
330 | .iova_to_phys = visconti_atu_iova_to_phys,
| ^~~~~~~~~~~~
drivers/iommu/visconti-atu.c:330:33: warning: excess elements in struct initializer
330 | .iova_to_phys = visconti_atu_iova_to_phys,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:330:33: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:331:18: error: 'const struct iommu_domain_ops' has no member named 'free'
331 | .free = visconti_atu_domain_free,
| ^~~~
drivers/iommu/visconti-atu.c:331:25: warning: excess elements in struct initializer
331 | .free = visconti_atu_domain_free,
| ^~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:331:25: note: (near initialization for '(anonymous)')
drivers/iommu/visconti-atu.c:325:64: error: invalid use of undefined type 'const struct iommu_domain_ops'
325 | .default_domain_ops = &(const struct iommu_domain_ops) {
| ^
drivers/iommu/visconti-atu.c:325:31: warning: excess elements in struct initializer
325 | .default_domain_ops = &(const struct iommu_domain_ops) {
| ^
drivers/iommu/visconti-atu.c:325:31: note: (near initialization for 'visconti_atu_ops')
drivers/iommu/visconti-atu.c: In function 'visconti_atu_probe':
drivers/iommu/visconti-atu.c:366:22: error: implicit declaration of function 'iommu_group_alloc' [-Werror=implicit-function-declaration]
366 | atu->group = iommu_group_alloc();
| ^~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:366:20: warning: assignment to 'struct iommu_group *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
366 | atu->group = iommu_group_alloc();
| ^
drivers/iommu/visconti-atu.c:380:15: error: implicit declaration of function 'iommu_device_sysfs_add' [-Werror=implicit-function-declaration]
380 | ret = iommu_device_sysfs_add(&atu->iommu, dev, NULL, dev_name(dev));
| ^~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:384:15: error: implicit declaration of function 'iommu_device_register'; did you mean 'of_device_register'? [-Werror=implicit-function-declaration]
384 | ret = iommu_device_register(&atu->iommu, &visconti_atu_ops, dev);
| ^~~~~~~~~~~~~~~~~~~~~
| of_device_register
drivers/iommu/visconti-atu.c:388:14: error: implicit declaration of function 'iommu_present'; did you mean 'pmd_present'? [-Werror=implicit-function-declaration]
388 | if (!iommu_present(&platform_bus_type))
| ^~~~~~~~~~~~~
| pmd_present
drivers/iommu/visconti-atu.c:389:17: error: implicit declaration of function 'bus_set_iommu' [-Werror=implicit-function-declaration]
389 | bus_set_iommu(&platform_bus_type, &visconti_atu_ops);
| ^~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:395:9: error: implicit declaration of function 'iommu_device_sysfs_remove' [-Werror=implicit-function-declaration]
395 | iommu_device_sysfs_remove(&atu->iommu);
| ^~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c: In function 'visconti_atu_remove':
drivers/iommu/visconti-atu.c:405:9: error: implicit declaration of function 'iommu_device_unregister'; did you mean 'of_device_unregister'? [-Werror=implicit-function-declaration]
405 | iommu_device_unregister(&atu->iommu);
| ^~~~~~~~~~~~~~~~~~~~~~~
| of_device_unregister
drivers/iommu/visconti-atu.c: At top level:
drivers/iommu/visconti-atu.c:318:31: error: storage size of 'visconti_atu_ops' isn't known
318 | static const struct iommu_ops visconti_atu_ops = {
| ^~~~~~~~~~~~~~~~
drivers/iommu/visconti-atu.c:318:31: error: storage size of 'visconti_atu_ops' isn't known
cc1: some warnings being treated as errors


vim +/iommu +47 drivers/iommu/visconti-atu.c

43
44 struct visconti_atu_device {
45 struct device *dev;
46 void __iomem *base;
> 47 struct iommu_device iommu;
48 struct iommu_group *group;
49
50 unsigned int num_entry;
51 unsigned int num_map_entry;
52 unsigned int enable_entry;
53 unsigned long iova[ATU_MAX_IOMMU_ENTRY];
54 phys_addr_t paddr[ATU_MAX_IOMMU_ENTRY];
55 size_t size[ATU_MAX_IOMMU_ENTRY];
56
57 spinlock_t lock;
58 };
59
60 struct visconti_atu_domain {
61 struct visconti_atu_device *atu;
> 62 struct iommu_domain io_domain;
63 struct mutex mutex;
64 };
65
66 static const struct iommu_ops visconti_atu_ops;
67
68 static struct visconti_atu_domain *to_atu_domain(struct iommu_domain *domain)
69 {
70 return container_of(domain, struct visconti_atu_domain, io_domain);
71 }
72
73 static inline void visconti_atu_write(struct visconti_atu_device *atu, u32 reg,
74 u32 val)
75 {
76 writel_relaxed(val, atu->base + reg);
77 }
78
79 static inline u32 visconti_atu_read(struct visconti_atu_device *atu, u32 reg)
80 {
81 return readl_relaxed(atu->base + reg);
82 }
83
84 static void visconti_atu_enable_entry(struct visconti_atu_device *atu,
85 int num)
86 {
87 dev_dbg(atu->dev, "enable ATU: %d\n", atu->enable_entry);
88
89 visconti_atu_write(atu, ATU_AT_EN, 0);
90 if (atu->enable_entry & BIT(num)) {
91 visconti_atu_write(atu,
92 ATU_AT_REG(num, ATU_AT_BLADDR),
93 atu->iova[num]);
94 visconti_atu_write(atu,
95 ATU_AT_REG(num, ATU_AT_ELADDR),
96 atu->iova[num] + atu->size[num] - 1);
97 visconti_atu_write(atu,
98 ATU_AT_REG(num, ATU_AT_BGADDR0),
99 atu->iova[num] & ATU_BGADDR_MASK);
100 visconti_atu_write(atu,
101 ATU_AT_REG(num, ATU_AT_BGADDR1),
102 (atu->iova[num] >> 32) & ATU_BGADDR_MASK);
103 }
104 visconti_atu_write(atu, ATU_AT_ENTRY_EN, atu->enable_entry);
105 visconti_atu_write(atu, ATU_AT_EN, 1);
106 }
107
108 static void visconti_atu_disable_entry(struct visconti_atu_device *atu)
109 {
110 dev_dbg(atu->dev, "disable ATU: %d\n", atu->enable_entry);
111
112 visconti_atu_write(atu, ATU_AT_EN, 0);
113 visconti_atu_write(atu, ATU_AT_ENTRY_EN, atu->enable_entry);
114 visconti_atu_write(atu, ATU_AT_EN, 1);
115 }
116
117 static int visconti_atu_attach_device(struct iommu_domain *io_domain,
118 struct device *dev)
119 {
120 struct visconti_atu_domain *domain = to_atu_domain(io_domain);
> 121 struct visconti_atu_device *atu = dev_iommu_priv_get(dev);
122 int ret = 0;
123
124 if (!atu) {
125 dev_err(dev, "Cannot attach to ATU\n");
126 return -ENXIO;
127 }
128
129 mutex_lock(&domain->mutex);
130
131 if (!domain->atu) {
132 domain->atu = atu;
133 } else if (domain->atu != atu) {
134 dev_err(dev, "Can't attach ATU %s to domain on ATU %s\n",
135 dev_name(atu->dev), dev_name(domain->atu->dev));
136 ret = -EINVAL;
137 } else {
138 dev_warn(dev, "Reusing ATU context\n");
139 }
140
141 mutex_unlock(&domain->mutex);
142
143 return ret;
144 }
145

--
0-DAY CI Kernel Test Service
https://01.org/lkp

2022-05-28 18:46:51

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

On Thu, May 26, 2022 at 12:43:25AM +0000, Tian, Kevin wrote:

> iiuc then this suggests there should be only one iommu group per atu,
> instead of using generic_device_group() to create one group per
> device.

Sounds like it

> > rejected then this driver should have a IOMMU_DOMAIN_BLOCKING and
> > return that from ops->def_domain_type().
>
> BLOCKING should not be used as a default domain type for DMA API
> which needs either a DMA or IDENTITY type.

New drivers should not have a NULL group->default_domain.

IMHO this driver does not support the DMA API so the default_domain
should be assigned to blocking and the DMA API disabled. We might need
some core changes to accommodate this.

The alternative would be to implement the identity domain, assuming
the ATU thing can store that kind of translation.

Jason

2022-05-28 19:46:49

by Tian, Kevin

[permalink] [raw]
Subject: RE: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

> From: Jason Gunthorpe
> Sent: Thursday, May 26, 2022 2:27 AM
>
> On Wed, May 25, 2022 at 02:26:37PM +0800, Baolu Lu wrote:
> > On 2022/5/25 09:31, Nobuhiro Iwamatsu wrote:
> > > +static const struct iommu_ops visconti_atu_ops = {
> > > + .domain_alloc = visconti_atu_domain_alloc,
> > > + .probe_device = visconti_atu_probe_device,
> > > + .release_device = visconti_atu_release_device,
> > > + .device_group = generic_device_group,
> > > + .of_xlate = visconti_atu_of_xlate,
> > > + .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
> > > + .default_domain_ops = &(const struct iommu_domain_ops) {
> > > + .attach_dev = visconti_atu_attach_device,
> > > + .detach_dev = visconti_atu_detach_device,
> >
> > The detach_dev callback is about to be deprecated. The new drivers
> > should implement the default domain and blocking domain instead.
>
> Yes please, new drivers need to use default_domains.
>
> It is very strange that visconti_atu_detach_device() does nothing. It
> is not required that a domain is fully unmapped before being
> destructed, I think detach should set ATU_AT_EN to 0.

Looks the atu is shared by all devices behind and can only serve one
I/O address space. The atu registers only keep information about
iova ranges without any device notation. That is probably the reason
why both attach/detach() don't touch hardware.

iiuc then this suggests there should be only one iommu group per atu,
instead of using generic_device_group() to create one group per
device.

>
> What behavior does the HW have when ATU_AT_ENTRY_EN == 0? If DMA is

I guess it's a blocking behavior since that register tracks which iova range
register is valid.

> rejected then this driver should have a IOMMU_DOMAIN_BLOCKING and
> return that from ops->def_domain_type().

BLOCKING should not be used as a default domain type for DMA API
which needs either a DMA or IDENTITY type.

>
> Attaching a the blocking domain should set ATU_AT_ENTRY_EN = 0

Agree

>
> Also, if I surmise how this works properly, it is not following the
> iommu API to halt all DMA during map/unmap operations. Should at least
> document this and explain why it is OK..
>
> I'm feeling like these "special" drivers need some kind of handshake
> with their only users because they don't work with things like VFIO..
>
> Jason

2022-06-20 02:34:21

by Nobuhiro Iwamatsu

[permalink] [raw]
Subject: RE: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

Hi,

> -----Original Message-----
> From: Baolu Lu <[email protected]>
> Sent: Wednesday, May 25, 2022 3:27 PM
> To: iwamatsu nobuhiro(岩松 信洋 □SWC◯ACT)
> <[email protected]>; Joerg Roedel <[email protected]>; Will
> Deacon <[email protected]>; Rob Herring <[email protected]>; Jason
> Gunthorpe <[email protected]>
> Cc: [email protected]; [email protected];
> [email protected]; [email protected]; ishikawa
> yuji(石川 悠司 ○RDC□AITC○EA開)
> <[email protected]>; [email protected]
> Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver
>
> On 2022/5/25 09:31, Nobuhiro Iwamatsu wrote:
> > +static const struct iommu_ops visconti_atu_ops = {
> > + .domain_alloc = visconti_atu_domain_alloc,
> > + .probe_device = visconti_atu_probe_device,
> > + .release_device = visconti_atu_release_device,
> > + .device_group = generic_device_group,
> > + .of_xlate = visconti_atu_of_xlate,
> > + .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
> > + .default_domain_ops = &(const struct iommu_domain_ops) {
> > + .attach_dev = visconti_atu_attach_device,
> > + .detach_dev = visconti_atu_detach_device,
>
> The detach_dev callback is about to be deprecated. The new drivers should
> implement the default domain and blocking domain instead.

I see. I will update this with next version.

>
> > + .map = visconti_atu_map,
> > + .unmap = visconti_atu_unmap,
> > + .iova_to_phys = visconti_atu_iova_to_phys,
> > + .free = visconti_atu_domain_free,
> > + }
> > +};
>
> Best regards,
> baolu

Best regards,
Nobuhiro

2022-06-20 06:15:45

by Nobuhiro Iwamatsu

[permalink] [raw]
Subject: RE: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

Hi,

Thanks for your review.

> -----Original Message-----
> From: Jason Gunthorpe <[email protected]>
> Sent: Thursday, May 26, 2022 3:27 AM
> To: Baolu Lu <[email protected]>
> Cc: iwamatsu nobuhiro($B4d>>(B $B?.MN(B $B""#S#W#C"~#A#C#T(B)
> <[email protected]>; Joerg Roedel <[email protected]>; Will
> Deacon <[email protected]>; Rob Herring <[email protected]>;
> [email protected]; [email protected];
> [email protected]; ishikawa yuji($B@P@n(B $BM*;J(B $B!{#R#D#C""#A#I#T(B
> $B#C!{#E#A3+(B) <[email protected]>;
> [email protected]
> Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver
>
> On Wed, May 25, 2022 at 02:26:37PM +0800, Baolu Lu wrote:
> > On 2022/5/25 09:31, Nobuhiro Iwamatsu wrote:
> > > +static const struct iommu_ops visconti_atu_ops = {
> > > + .domain_alloc = visconti_atu_domain_alloc,
> > > + .probe_device = visconti_atu_probe_device,
> > > + .release_device = visconti_atu_release_device,
> > > + .device_group = generic_device_group,
> > > + .of_xlate = visconti_atu_of_xlate,
> > > + .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
> > > + .default_domain_ops = &(const struct iommu_domain_ops) {
> > > + .attach_dev = visconti_atu_attach_device,
> > > + .detach_dev = visconti_atu_detach_device,
> >
> > The detach_dev callback is about to be deprecated. The new drivers
> > should implement the default domain and blocking domain instead.
>
> Yes please, new drivers need to use default_domains.
>
> It is very strange that visconti_atu_detach_device() does nothing. It is not
> required that a domain is fully unmapped before being destructed, I think
> detach should set ATU_AT_EN to 0.

I see, I rethink implementation.

>
> What behavior does the HW have when ATU_AT_ENTRY_EN == 0? If DMA is
> rejected then this driver should have a IOMMU_DOMAIN_BLOCKING and
> return that from ops->def_domain_type().

If ATU_AT_ENTRY_EN is 0, nothing happens. It does not work with IOMMU,
it works with the memory space set in device tree.
Also, I investigate about IOMMU_DOMAIN_BLOCKING.

>
> Attaching a the blocking domain should set ATU_AT_ENTRY_EN = 0
>
> Also, if I surmise how this works properly, it is not following the iommu API to
> halt all DMA during map/unmap operations. Should at least document this and
> explain why it is OK..

I see, I will check DMA during map and unmap operations.

>
> I'm feeling like these "special" drivers need some kind of handshake with their
> only users because they don't work with things like VFIO..

Since the devices that utilize this IOMMU function are fixed, I do not think that a special handshake is required.
Could you you tell me where you thought you needed a handshake?

Best regards,
Nobuhiro

>
> Jason

2022-06-24 13:40:45

by Jason Gunthorpe

[permalink] [raw]
Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver

On Mon, Jun 20, 2022 at 05:49:13AM +0000, [email protected] wrote:
> Hi,
>
> Thanks for your review.
>
> > -----Original Message-----
> > From: Jason Gunthorpe <[email protected]>
> > Sent: Thursday, May 26, 2022 3:27 AM
> > To: Baolu Lu <[email protected]>
> > Cc: iwamatsu nobuhiro(岩松 信洋 □SWC◯ACT)
> > <[email protected]>; Joerg Roedel <[email protected]>; Will
> > Deacon <[email protected]>; Rob Herring <[email protected]>;
> > [email protected]; [email protected];
> > [email protected]; ishikawa yuji(石川 悠司 ○RDC□AIT
> > C○EA開) <[email protected]>;
> > [email protected]
> > Subject: Re: [PATCH 1/3] iommu: Add Visconti5 IOMMU driver
> >
> > On Wed, May 25, 2022 at 02:26:37PM +0800, Baolu Lu wrote:
> > > On 2022/5/25 09:31, Nobuhiro Iwamatsu wrote:
> > > > +static const struct iommu_ops visconti_atu_ops = {
> > > > + .domain_alloc = visconti_atu_domain_alloc,
> > > > + .probe_device = visconti_atu_probe_device,
> > > > + .release_device = visconti_atu_release_device,
> > > > + .device_group = generic_device_group,
> > > > + .of_xlate = visconti_atu_of_xlate,
> > > > + .pgsize_bitmap = ATU_IOMMU_PGSIZE_BITMAP,
> > > > + .default_domain_ops = &(const struct iommu_domain_ops) {
> > > > + .attach_dev = visconti_atu_attach_device,
> > > > + .detach_dev = visconti_atu_detach_device,
> > >
> > > The detach_dev callback is about to be deprecated. The new drivers
> > > should implement the default domain and blocking domain instead.
> >
> > Yes please, new drivers need to use default_domains.
> >
> > It is very strange that visconti_atu_detach_device() does nothing. It is not
> > required that a domain is fully unmapped before being destructed, I think
> > detach should set ATU_AT_EN to 0.
>
> I see, I rethink implementation.
>
> >
> > What behavior does the HW have when ATU_AT_ENTRY_EN == 0? If DMA is
> > rejected then this driver should have a IOMMU_DOMAIN_BLOCKING and
> > return that from ops->def_domain_type().
>
> If ATU_AT_ENTRY_EN is 0, nothing happens. It does not work with IOMMU,
> it works with the memory space set in device tree.

So that would be an assignment to DOMAIN_IDENTITY

> > I'm feeling like these "special" drivers need some kind of handshake with their
> > only users because they don't work with things like VFIO..
>
> Since the devices that utilize this IOMMU function are fixed, I do
> not think that a special handshake is required. Could you you tell
> me where you thought you needed a handshake?

In this case the iommu driver is so limited that it will not work with
VFIO - it is only ment to be used with the fixed drivers that are
paired with it.

Ideally we'd prevent VFIO from connecting and only allow drivers that
know the limitations of the IOMMU to use the unmanaged domain.

Jason