Merge tag 'iommu-updates-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel: - PASID table handling updates for the Intel VT-d driver. It implements a global PASID space now so that applications usings multiple devices will just have one PASID. - A new config option to make iommu passthroug mode the default. - New sysfs attribute for iommu groups to export the type of the default domain. - A debugfs interface (for debug only) usable by IOMMU drivers to export internals to user-space. - R-Car Gen3 SoCs support for the ipmmu-vmsa driver - The ARM-SMMU now aborts transactions from unknown devices and devices not attached to any domain. - Various cleanups and smaller fixes all over the place. * tag 'iommu-updates-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (42 commits) iommu/omap: Fix cache flushes on L2 table entries iommu: Remove the ->map_sg indirection iommu/arm-smmu-v3: Abort all transactions if SMMU is enabled in kdump kernel iommu/arm-smmu-v3: Prevent any devices access to memory without registration iommu/ipmmu-vmsa: Don't register as BUS IOMMU if machine doesn't have IPMMU-VMSA iommu/ipmmu-vmsa: Clarify supported platforms iommu/ipmmu-vmsa: Fix allocation in atomic context iommu: Add config option to set passthrough as default iommu: Add sysfs attribyte for domain type iommu/arm-smmu-v3: sync the OVACKFLG to PRIQ consumer register iommu/arm-smmu: Error out only if not enough context interrupts iommu/io-pgtable-arm-v7s: Abort allocation when table address overflows the PTE iommu/io-pgtable-arm: Fix pgtable allocation in selftest iommu/vt-d: Remove the obsolete per iommu pasid tables iommu/vt-d: Apply per pci device pasid table in SVA iommu/vt-d: Allocate and free pasid table iommu/vt-d: Per PCI device pasid table interfaces iommu/vt-d: Add for_each_device_domain() helper iommu/vt-d: Move device_domain_info to header iommu/vt-d: Apply global PASID in SVA ...
This commit is contained in:
@@ -47,6 +47,7 @@ struct ipmmu_features {
|
||||
unsigned int number_of_contexts;
|
||||
bool setup_imbuscr;
|
||||
bool twobit_imttbcr_sl0;
|
||||
bool reserved_context;
|
||||
};
|
||||
|
||||
struct ipmmu_vmsa_device {
|
||||
@@ -73,7 +74,7 @@ struct ipmmu_vmsa_domain {
|
||||
struct io_pgtable_ops *iop;
|
||||
|
||||
unsigned int context_id;
|
||||
spinlock_t lock; /* Protects mappings */
|
||||
struct mutex mutex; /* Protects mappings */
|
||||
};
|
||||
|
||||
static struct ipmmu_vmsa_domain *to_vmsa_domain(struct iommu_domain *dom)
|
||||
@@ -194,7 +195,9 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
|
||||
#define IMPMBA(n) (0x0280 + ((n) * 4))
|
||||
#define IMPMBD(n) (0x02c0 + ((n) * 4))
|
||||
|
||||
#define IMUCTR(n) (0x0300 + ((n) * 16))
|
||||
#define IMUCTR(n) ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
|
||||
#define IMUCTR0(n) (0x0300 + ((n) * 16))
|
||||
#define IMUCTR32(n) (0x0600 + (((n) - 32) * 16))
|
||||
#define IMUCTR_FIXADDEN (1 << 31)
|
||||
#define IMUCTR_FIXADD_MASK (0xff << 16)
|
||||
#define IMUCTR_FIXADD_SHIFT 16
|
||||
@@ -204,7 +207,9 @@ static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
|
||||
#define IMUCTR_FLUSH (1 << 1)
|
||||
#define IMUCTR_MMUEN (1 << 0)
|
||||
|
||||
#define IMUASID(n) (0x0308 + ((n) * 16))
|
||||
#define IMUASID(n) ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
|
||||
#define IMUASID0(n) (0x0308 + ((n) * 16))
|
||||
#define IMUASID32(n) (0x0608 + (((n) - 32) * 16))
|
||||
#define IMUASID_ASID8_MASK (0xff << 8)
|
||||
#define IMUASID_ASID8_SHIFT 8
|
||||
#define IMUASID_ASID0_MASK (0xff << 0)
|
||||
@@ -595,7 +600,7 @@ static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
|
||||
if (!domain)
|
||||
return NULL;
|
||||
|
||||
spin_lock_init(&domain->lock);
|
||||
mutex_init(&domain->mutex);
|
||||
|
||||
return &domain->io_domain;
|
||||
}
|
||||
@@ -641,7 +646,6 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
|
||||
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
|
||||
struct ipmmu_vmsa_device *mmu = to_ipmmu(dev);
|
||||
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
|
||||
@@ -650,7 +654,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&domain->lock, flags);
|
||||
mutex_lock(&domain->mutex);
|
||||
|
||||
if (!domain->mmu) {
|
||||
/* The domain hasn't been used yet, initialize it. */
|
||||
@@ -674,7 +678,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
|
||||
} else
|
||||
dev_info(dev, "Reusing IPMMU context %u\n", domain->context_id);
|
||||
|
||||
spin_unlock_irqrestore(&domain->lock, flags);
|
||||
mutex_unlock(&domain->mutex);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@@ -756,8 +760,12 @@ static bool ipmmu_slave_whitelist(struct device *dev)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct soc_device_attribute soc_r8a7795[] = {
|
||||
static const struct soc_device_attribute soc_rcar_gen3[] = {
|
||||
{ .soc_id = "r8a7795", },
|
||||
{ .soc_id = "r8a7796", },
|
||||
{ .soc_id = "r8a77965", },
|
||||
{ .soc_id = "r8a77970", },
|
||||
{ .soc_id = "r8a77995", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@@ -765,7 +773,7 @@ static int ipmmu_of_xlate(struct device *dev,
|
||||
struct of_phandle_args *spec)
|
||||
{
|
||||
/* For R-Car Gen3 use a white list to opt-in slave devices */
|
||||
if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
|
||||
if (soc_device_match(soc_rcar_gen3) && !ipmmu_slave_whitelist(dev))
|
||||
return -ENODEV;
|
||||
|
||||
iommu_fwspec_add_ids(dev, spec->args, 1);
|
||||
@@ -889,7 +897,6 @@ static const struct iommu_ops ipmmu_ops = {
|
||||
.unmap = ipmmu_unmap,
|
||||
.flush_iotlb_all = ipmmu_iotlb_sync,
|
||||
.iotlb_sync = ipmmu_iotlb_sync,
|
||||
.map_sg = default_iommu_map_sg,
|
||||
.iova_to_phys = ipmmu_iova_to_phys,
|
||||
.add_device = ipmmu_add_device,
|
||||
.remove_device = ipmmu_remove_device,
|
||||
@@ -917,14 +924,16 @@ static const struct ipmmu_features ipmmu_features_default = {
|
||||
.number_of_contexts = 1, /* software only tested with one context */
|
||||
.setup_imbuscr = true,
|
||||
.twobit_imttbcr_sl0 = false,
|
||||
.reserved_context = false,
|
||||
};
|
||||
|
||||
static const struct ipmmu_features ipmmu_features_r8a7795 = {
|
||||
static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
|
||||
.use_ns_alias_offset = false,
|
||||
.has_cache_leaf_nodes = true,
|
||||
.number_of_contexts = 8,
|
||||
.setup_imbuscr = false,
|
||||
.twobit_imttbcr_sl0 = true,
|
||||
.reserved_context = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id ipmmu_of_ids[] = {
|
||||
@@ -933,7 +942,19 @@ static const struct of_device_id ipmmu_of_ids[] = {
|
||||
.data = &ipmmu_features_default,
|
||||
}, {
|
||||
.compatible = "renesas,ipmmu-r8a7795",
|
||||
.data = &ipmmu_features_r8a7795,
|
||||
.data = &ipmmu_features_rcar_gen3,
|
||||
}, {
|
||||
.compatible = "renesas,ipmmu-r8a7796",
|
||||
.data = &ipmmu_features_rcar_gen3,
|
||||
}, {
|
||||
.compatible = "renesas,ipmmu-r8a77965",
|
||||
.data = &ipmmu_features_rcar_gen3,
|
||||
}, {
|
||||
.compatible = "renesas,ipmmu-r8a77970",
|
||||
.data = &ipmmu_features_rcar_gen3,
|
||||
}, {
|
||||
.compatible = "renesas,ipmmu-r8a77995",
|
||||
.data = &ipmmu_features_rcar_gen3,
|
||||
}, {
|
||||
/* Terminator */
|
||||
},
|
||||
@@ -955,7 +976,7 @@ static int ipmmu_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
mmu->dev = &pdev->dev;
|
||||
mmu->num_utlbs = 32;
|
||||
mmu->num_utlbs = 48;
|
||||
spin_lock_init(&mmu->lock);
|
||||
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
|
||||
mmu->features = of_device_get_match_data(&pdev->dev);
|
||||
@@ -1018,6 +1039,11 @@ static int ipmmu_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ipmmu_device_reset(mmu);
|
||||
|
||||
if (mmu->features->reserved_context) {
|
||||
dev_info(&pdev->dev, "IPMMU context 0 is reserved\n");
|
||||
set_bit(0, mmu->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1081,12 +1107,19 @@ static struct platform_driver ipmmu_driver = {
|
||||
|
||||
static int __init ipmmu_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
static bool setup_done;
|
||||
int ret;
|
||||
|
||||
if (setup_done)
|
||||
return 0;
|
||||
|
||||
np = of_find_matching_node(NULL, ipmmu_of_ids);
|
||||
if (!np)
|
||||
return 0;
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
ret = platform_driver_register(&ipmmu_driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
Reference in New Issue
Block a user