On Mon, Sep 28, 2020 at 02:38:31PM -0700, Jacob Pan wrote: > IOASID is a system-wide resource that could vary on different systems. > The default capacity is 20 bits as defined in the PCI-E specifications. > This patch adds a function to allow adjusting system IOASID capacity. > For VT-d this is set during boot as part of the Intel IOMMU > initialization. > > Signed-off-by: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx> Reviewed-by: Jean-Philippe Brucker <jean-philippe@xxxxxxxxxx> > --- > drivers/iommu/intel/iommu.c | 5 +++++ > drivers/iommu/ioasid.c | 20 ++++++++++++++++++++ > include/linux/ioasid.h | 11 +++++++++++ > 3 files changed, 36 insertions(+) > > diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c > index 18ed3b3c70d7..e7bcb299e51e 100644 > --- a/drivers/iommu/intel/iommu.c > +++ b/drivers/iommu/intel/iommu.c > @@ -42,6 +42,7 @@ > #include <linux/crash_dump.h> > #include <linux/numa.h> > #include <linux/swiotlb.h> > +#include <linux/ioasid.h> (not in alphabetical order) > #include <asm/irq_remapping.h> > #include <asm/cacheflush.h> > #include <asm/iommu.h> > @@ -3331,6 +3332,10 @@ static int __init init_dmars(void) > if (ret) > goto free_iommu; > > + /* PASID is needed for scalable mode irrespective to SVM */ > + if (intel_iommu_sm) > + ioasid_install_capacity(intel_pasid_max_id); > + > /* > * for each drhd > * enable fault log > diff --git a/drivers/iommu/ioasid.c b/drivers/iommu/ioasid.c > index 6cfbdfb492e0..4277cb17e15b 100644 > --- a/drivers/iommu/ioasid.c > +++ b/drivers/iommu/ioasid.c > @@ -10,6 +10,10 @@ > #include <linux/spinlock.h> > #include <linux/xarray.h> > > +/* Default to PCIe standard 20 bit PASID */ > +#define PCI_PASID_MAX 0x100000 > +static ioasid_t ioasid_capacity = PCI_PASID_MAX; > +static ioasid_t ioasid_capacity_avail = PCI_PASID_MAX; > struct ioasid_data { > ioasid_t id; > struct ioasid_set *set; > @@ -17,6 +21,22 @@ struct ioasid_data { > struct rcu_head rcu; > }; > > +void ioasid_install_capacity(ioasid_t total) > +{ > + if (ioasid_capacity && ioasid_capacity != PCI_PASID_MAX) { > + pr_warn("IOASID capacity is already set.\n"); > + return; > + } > + ioasid_capacity = ioasid_capacity_avail = total; > +} > +EXPORT_SYMBOL_GPL(ioasid_install_capacity); > + > +ioasid_t ioasid_get_capacity(void) > +{ > + return ioasid_capacity; > +} > +EXPORT_SYMBOL_GPL(ioasid_get_capacity); > + > /* > * struct ioasid_allocator_data - Internal data structure to hold information > * about an allocator. There are two types of allocators: > diff --git a/include/linux/ioasid.h b/include/linux/ioasid.h > index c7f649fa970a..7fc320656be2 100644 > --- a/include/linux/ioasid.h > +++ b/include/linux/ioasid.h > @@ -32,6 +32,8 @@ struct ioasid_allocator_ops { > #define DECLARE_IOASID_SET(name) struct ioasid_set name = { 0 } > > #if IS_ENABLED(CONFIG_IOASID) > +void ioasid_install_capacity(ioasid_t total); > +ioasid_t ioasid_get_capacity(void); > ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, > void *private); > void ioasid_free(ioasid_t ioasid); > @@ -42,6 +44,15 @@ void ioasid_unregister_allocator(struct ioasid_allocator_ops *allocator); > int ioasid_attach_data(ioasid_t ioasid, void *data); > void ioasid_detach_data(ioasid_t ioasid); > #else /* !CONFIG_IOASID */ > +static inline void ioasid_install_capacity(ioasid_t total) > +{ > +} > + > +static inline ioasid_t ioasid_get_capacity(void) > +{ > + return 0; > +} > + > static inline ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, > ioasid_t max, void *private) > { > -- > 2.7.4 >