[PATCH 2/7] iommu/arm-smmu: Introduce bus notifier block
Andreas Herrmann
andreas.herrmann at calxeda.com
Thu Oct 10 12:47:59 EDT 2013
On Thu, Oct 10, 2013 at 12:12:17PM -0400, Will Deacon wrote:
> On Wed, Oct 09, 2013 at 11:38:01PM +0100, Andreas Herrmann wrote:
> > drivers/iommu/arm-smmu.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 53 insertions(+)
> >
> > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> > index 478c8ad..87239e8 100644
> > --- a/drivers/iommu/arm-smmu.c
> > +++ b/drivers/iommu/arm-smmu.c
> > @@ -46,6 +46,7 @@
> > #include <linux/amba/bus.h>
> >
> > #include <asm/pgalloc.h>
> > +#include <asm/dma-iommu.h>
> >
> > /* Driver options */
> > #define ARM_SMMU_OPT_ISOLATE_DEVICES (1 << 0)
> > @@ -1983,6 +1984,56 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static int arm_smmu_device_notifier(struct notifier_block *nb,
> > + unsigned long action, void *data)
> > +{
> > + struct device *dev = data;
> > + struct dma_iommu_mapping *mapping;
> > + struct arm_smmu_device *smmu;
> > + void __iomem *gr0_base;
> > + u32 cr0;
> > + int ret;
> > +
> > + switch (action) {
> > + case BUS_NOTIFY_BIND_DRIVER:
> > +
> > + arm_smmu_add_device(dev);
> > + smmu = dev->archdata.iommu;
> > + if (!smmu || !(smmu->options & ARM_SMMU_OPT_ISOLATE_DEVICES))
> > + break;
> > +
> > + mapping = arm_iommu_create_mapping(&platform_bus_type,
> > + 0, SZ_128M, 0);
>
> We need to find a better way of doing this; I'm really not happy hardcoding
> that size limit and hoping for the best.
Hmm, seems that mid-term we should try to enlarge this area by another
128M if a mapping fails due to this limit. I think Joerg's amd_iommu
driver does this.
(But at the same time I'd prefer to start with even a hardcoded value,
or to simply introduce some option to set this fixed limit per master
or per smmu.)
> > + if (IS_ERR(mapping)) {
> > + ret = PTR_ERR(mapping);
> > + dev_info(dev, "arm_iommu_create_mapping failed\n");
> > + break;
> > + }
> > +
> > + ret = arm_iommu_attach_device(dev, mapping);
> > + if (ret < 0) {
> > + dev_info(dev, "arm_iommu_attach_device failed\n");
> > + arm_iommu_release_mapping(mapping);
> > + }
> > +
> > + gr0_base = ARM_SMMU_GR0_NS(smmu);
> > + cr0 = readl_relaxed(gr0_base + ARM_SMMU_GR0_sCR0);
> > + cr0 |= sCR0_USFCFG;
> > + writel(cr0, gr0_base + ARM_SMMU_GR0_sCR0);
>
> Why do you need to enable this flag? If no mapping is found, that means *we*
> screwed something up, so we should report that and not rely on the hardware
> potentially raising a fault. I also prefer to allow passthrough for devices
> that don't hit in the stream table, because it allows people to ignore the SMMU
> in their DT if they want to.
You are right that's not strictly required for device isolation.
(but it helped to learn about relevant stream-ids that were not
covered by by my DTS ;-)
Andreas
More information about the linux-arm-kernel
mailing list