Skip to content

Commit

Permalink
iommu/riscv: Enable IOMMU registration and device probe.
Browse files Browse the repository at this point in the history
Advertise IOMMU device and its core API.
Only minimal implementation for single identity domain type, without
per-group domain protection.

Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Zong Li <zong.li@sifive.com>
Signed-off-by: Tomasz Jeznach <tjeznach@rivosinc.com>
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
Link: https://lore.kernel.org/r/ba79c8eb9c7f1cd9a8961a1b048e3991ee9a2b05.1729059707.git.tjeznach@rivosinc.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Tomasz Jeznach authored and Joerg Roedel committed Oct 29, 2024
1 parent 68682e9 commit 822e8bc
Showing 1 changed file with 66 additions and 0 deletions.
66 changes: 66 additions & 0 deletions drivers/iommu/riscv/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/iommu.h>
#include <linux/kernel.h>
#include <linux/pci.h>

#include "iommu-bits.h"
#include "iommu.h"
Expand All @@ -36,6 +37,60 @@ static void riscv_iommu_disable(struct riscv_iommu_device *iommu)
riscv_iommu_writel(iommu, RISCV_IOMMU_REG_PQCSR, 0);
}

static int riscv_iommu_attach_identity_domain(struct iommu_domain *iommu_domain,
struct device *dev)
{
/* Global pass-through already enabled, do nothing for now. */
return 0;
}

static struct iommu_domain riscv_iommu_identity_domain = {
.type = IOMMU_DOMAIN_IDENTITY,
.ops = &(const struct iommu_domain_ops) {
.attach_dev = riscv_iommu_attach_identity_domain,
}
};

static int riscv_iommu_device_domain_type(struct device *dev)
{
return IOMMU_DOMAIN_IDENTITY;
}

static struct iommu_group *riscv_iommu_device_group(struct device *dev)
{
if (dev_is_pci(dev))
return pci_device_group(dev);
return generic_device_group(dev);
}

static int riscv_iommu_of_xlate(struct device *dev, const struct of_phandle_args *args)
{
return iommu_fwspec_add_ids(dev, args->args, 1);
}

static struct iommu_device *riscv_iommu_probe_device(struct device *dev)
{
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct riscv_iommu_device *iommu;

if (!fwspec || !fwspec->iommu_fwnode->dev || !fwspec->num_ids)
return ERR_PTR(-ENODEV);

iommu = dev_get_drvdata(fwspec->iommu_fwnode->dev);
if (!iommu)
return ERR_PTR(-ENODEV);

return &iommu->iommu;
}

static const struct iommu_ops riscv_iommu_ops = {
.of_xlate = riscv_iommu_of_xlate,
.identity_domain = &riscv_iommu_identity_domain,
.def_domain_type = riscv_iommu_device_domain_type,
.device_group = riscv_iommu_device_group,
.probe_device = riscv_iommu_probe_device,
};

static int riscv_iommu_init_check(struct riscv_iommu_device *iommu)
{
u64 ddtp;
Expand Down Expand Up @@ -74,6 +129,7 @@ static int riscv_iommu_init_check(struct riscv_iommu_device *iommu)

void riscv_iommu_remove(struct riscv_iommu_device *iommu)
{
iommu_device_unregister(&iommu->iommu);
iommu_device_sysfs_remove(&iommu->iommu);
}

Expand All @@ -99,5 +155,15 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
return dev_err_probe(iommu->dev, rc,
"cannot register sysfs interface\n");

rc = iommu_device_register(&iommu->iommu, &riscv_iommu_ops, iommu->dev);
if (rc) {
dev_err_probe(iommu->dev, rc, "cannot register iommu interface\n");
goto err_remove_sysfs;
}

return 0;

err_remove_sysfs:
iommu_device_sysfs_remove(&iommu->iommu);
return rc;
}

0 comments on commit 822e8bc

Please sign in to comment.