Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions arch/powerpc/kernel/iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1280,21 +1280,27 @@ struct iommu_table_group_ops spapr_tce_table_group_ops = {
/*
* A simple iommu_ops to allow less cruft in generic VFIO code.
*/
static int spapr_tce_platform_iommu_attach_dev(struct iommu_domain *dom,
struct device *dev)
static int
spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain,
struct device *dev)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
struct iommu_group *grp = iommu_group_get(dev);
struct iommu_table_group *table_group;
int ret = -EINVAL;

if (!grp)
return -ENODEV;
/* At first attach the ownership is already set */
if (!domain)
return 0;

table_group = iommu_group_get_iommudata(grp);
ret = table_group->ops->take_ownership(table_group);
/*
* The domain being set to PLATFORM from earlier
* BLOCKED. The table_group ownership has to be released.
*/
table_group->ops->release_ownership(table_group);
iommu_group_put(grp);

return ret;
return 0;
}

static const struct iommu_domain_ops spapr_tce_platform_domain_ops = {
Expand All @@ -1306,13 +1312,32 @@ static struct iommu_domain spapr_tce_platform_domain = {
.ops = &spapr_tce_platform_domain_ops,
};

static struct iommu_domain spapr_tce_blocked_domain = {
.type = IOMMU_DOMAIN_BLOCKED,
static int
spapr_tce_blocked_iommu_attach_dev(struct iommu_domain *platform_domain,
struct device *dev)
{
struct iommu_group *grp = iommu_group_get(dev);
struct iommu_table_group *table_group;
int ret = -EINVAL;

/*
* FIXME: SPAPR mixes blocked and platform behaviors, the blocked domain
* also sets the dma_api ops
*/
.ops = &spapr_tce_platform_domain_ops,
table_group = iommu_group_get_iommudata(grp);
ret = table_group->ops->take_ownership(table_group);
iommu_group_put(grp);

return ret;
}

static const struct iommu_domain_ops spapr_tce_blocked_domain_ops = {
.attach_dev = spapr_tce_blocked_iommu_attach_dev,
};

static struct iommu_domain spapr_tce_blocked_domain = {
.type = IOMMU_DOMAIN_BLOCKED,
.ops = &spapr_tce_blocked_domain_ops,
};

static bool spapr_tce_iommu_capable(struct device *dev, enum iommu_cap cap)
Expand Down
39 changes: 39 additions & 0 deletions drivers/iommu/arm/arm-smmu/qcom_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,44 @@ static int qcom_iommu_attach_dev(struct iommu_domain *domain, struct device *dev
return 0;
}

static int qcom_iommu_identity_attach(struct iommu_domain *identity_domain,
struct device *dev)
{
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
struct qcom_iommu_domain *qcom_domain;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct qcom_iommu_dev *qcom_iommu = to_iommu(dev);
unsigned int i;

if (domain == identity_domain || !domain)
return 0;

qcom_domain = to_qcom_iommu_domain(domain);
if (WARN_ON(!qcom_domain->iommu))
return -EINVAL;

pm_runtime_get_sync(qcom_iommu->dev);
for (i = 0; i < fwspec->num_ids; i++) {
struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]);

/* Disable the context bank: */
iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0);

ctx->domain = NULL;
}
pm_runtime_put_sync(qcom_iommu->dev);
return 0;
}

static struct iommu_domain_ops qcom_iommu_identity_ops = {
.attach_dev = qcom_iommu_identity_attach,
};

static struct iommu_domain qcom_iommu_identity_domain = {
.type = IOMMU_DOMAIN_IDENTITY,
.ops = &qcom_iommu_identity_ops,
};

static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
phys_addr_t paddr, size_t pgsize, size_t pgcount,
int prot, gfp_t gfp, size_t *mapped)
Expand Down Expand Up @@ -563,6 +601,7 @@ static int qcom_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
}

static const struct iommu_ops qcom_iommu_ops = {
.identity_domain = &qcom_iommu_identity_domain,
.capable = qcom_iommu_capable,
.domain_alloc = qcom_iommu_domain_alloc,
.probe_device = qcom_iommu_probe_device,
Expand Down
Loading