Message ID | 20230602182212.150825-3-jacob.jun.pan@linux.intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Re-enable IDXD kernel workqueue under DMA API | expand |
On 6/3/23 2:22 AM, Jacob Pan wrote: > +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) > +{ > + int ret; > + ioasid_t max; > + > + max = dev->iommu->max_pasids; > + /* > + * max_pasids is set up by vendor driver based on number of PASID bits > + * supported but the IDA allocation is inclusive. > + */ > + ret = ida_alloc_range(&iommu_global_pasid_ida, IOMMU_FIRST_GLOBAL_PASID, max - 1, GFP_KERNEL); > + if (ret < 0) > + return IOMMU_PASID_INVALID; > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); "dev->iommu->max_pasids == 0" indicates no pasid support on the device. The code should return IOMMU_PASID_INVALID explicitly. Perhaps we can make this function like this: ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) { int ret; if (!dev->iommu->max_pasids) return IOMMU_PASID_INVALID; /* * max_pasids is set up by vendor driver based on number of PASID bits * supported but the IDA allocation is inclusive. */ ret = ida_alloc_range(&iommu_global_pasid_ida, IOMMU_FIRST_GLOBAL_PASID, dev->iommu->max_pasids - 1, GFP_KERNEL); return ret < 0 ? IOMMU_PASID_INVALID : ret; } EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); Other change in this series looks good to me. I hope I can queue this series including above change as part of my VT-d update for v6.5 to Joerg if no objection. Let's try to re-enable this key feature of Intel idxd driver in v6.5. Best regards, baolu
On 6/10/23 8:13 PM, Baolu Lu wrote: > On 6/3/23 2:22 AM, Jacob Pan wrote: >> +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) >> +{ >> + int ret; >> + ioasid_t max; >> + >> + max = dev->iommu->max_pasids; >> + /* >> + * max_pasids is set up by vendor driver based on number of PASID >> bits >> + * supported but the IDA allocation is inclusive. >> + */ >> + ret = ida_alloc_range(&iommu_global_pasid_ida, >> IOMMU_FIRST_GLOBAL_PASID, max - 1, GFP_KERNEL); >> + if (ret < 0) >> + return IOMMU_PASID_INVALID; >> + >> + return ret; >> +} >> +EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); > > "dev->iommu->max_pasids == 0" indicates no pasid support on the device. > The code should return IOMMU_PASID_INVALID explicitly. Perhaps we can > make this function like this: > > ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) > { > int ret; > > if (!dev->iommu->max_pasids) > return IOMMU_PASID_INVALID; > > /* > * max_pasids is set up by vendor driver based on number of > PASID bits > * supported but the IDA allocation is inclusive. > */ > ret = ida_alloc_range(&iommu_global_pasid_ida, > IOMMU_FIRST_GLOBAL_PASID, > dev->iommu->max_pasids - 1, GFP_KERNEL); > > return ret < 0 ? IOMMU_PASID_INVALID : ret; > } > EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); > > Other change in this series looks good to me. > > I hope I can queue this series including above change as part of my VT-d > update for v6.5 to Joerg if no objection. > > Let's try to re-enable this key feature of Intel idxd driver in v6.5. This series didn't pass my test. The first time when I run "idxd_ktest.sh -c 1 -t 1 -i 100 -m shared", it passed. But when I run it again, the idxd hardware operation resulted in timed-out issues. I have removed this series from my queue. Best regards, baolu
Hi Baolu, On Tue, 13 Jun 2023 11:06:03 +0800, Baolu Lu <baolu.lu@linux.intel.com> wrote: > On 6/10/23 8:13 PM, Baolu Lu wrote: > > On 6/3/23 2:22 AM, Jacob Pan wrote: > >> +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) > >> +{ > >> + int ret; > >> + ioasid_t max; > >> + > >> + max = dev->iommu->max_pasids; > >> + /* > >> + * max_pasids is set up by vendor driver based on number of PASID > >> bits > >> + * supported but the IDA allocation is inclusive. > >> + */ > >> + ret = ida_alloc_range(&iommu_global_pasid_ida, > >> IOMMU_FIRST_GLOBAL_PASID, max - 1, GFP_KERNEL); > >> + if (ret < 0) > >> + return IOMMU_PASID_INVALID; > >> + > >> + return ret; > >> +} > >> +EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); > > > > "dev->iommu->max_pasids == 0" indicates no pasid support on the device. > > The code should return IOMMU_PASID_INVALID explicitly. Perhaps we can > > make this function like this: > > > > ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) > > { > > int ret; > > > > if (!dev->iommu->max_pasids) > > return IOMMU_PASID_INVALID; > > > > /* > > * max_pasids is set up by vendor driver based on number of > > PASID bits > > * supported but the IDA allocation is inclusive. > > */ > > ret = ida_alloc_range(&iommu_global_pasid_ida, > > IOMMU_FIRST_GLOBAL_PASID, > > dev->iommu->max_pasids - 1, GFP_KERNEL); > > > > return ret < 0 ? IOMMU_PASID_INVALID : ret; > > } > > EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); > > > > Other change in this series looks good to me. > > > > I hope I can queue this series including above change as part of my VT-d > > update for v6.5 to Joerg if no objection. > > > > Let's try to re-enable this key feature of Intel idxd driver in v6.5. > > This series didn't pass my test. > > The first time when I run "idxd_ktest.sh -c 1 -t 1 -i 100 -m shared", it > passed. But when I run it again, the idxd hardware operation resulted in > timed-out issues. > Hmm, not sure what happened. Are you using the out of tree idxd_ktest kernel module or the dmaengine test sysfs? e.g. echo "Config params for DMA test" echo $1 > /sys/module/dmatest/parameters/iterations #echo 1 > /sys/module/dmatest/parameters/noverify echo "" > /sys/module/dmatest/parameters/channel echo 1 > /sys/module/dmatest/parameters/run sleep 2 echo 0 > /sys/module/dmatest/parameters/run echo "Completed!" It passed my test many iterations for shared in-kernel DSA test, will get your tree and test again. Thanks, Jacob
Hi Baolu, On Sat, 10 Jun 2023 20:13:03 +0800, Baolu Lu <baolu.lu@linux.intel.com> wrote: > On 6/3/23 2:22 AM, Jacob Pan wrote: > > +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) > > +{ > > + int ret; > > + ioasid_t max; > > + > > + max = dev->iommu->max_pasids; > > + /* > > + * max_pasids is set up by vendor driver based on number of > > PASID bits > > + * supported but the IDA allocation is inclusive. > > + */ > > + ret = ida_alloc_range(&iommu_global_pasid_ida, > > IOMMU_FIRST_GLOBAL_PASID, max - 1, GFP_KERNEL); > > + if (ret < 0) > > + return IOMMU_PASID_INVALID; > > + > > + return ret; > > +} > > +EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); > > "dev->iommu->max_pasids == 0" indicates no pasid support on the device. > The code should return IOMMU_PASID_INVALID explicitly. Perhaps we can > make this function like this: > > ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) > { > int ret; > > if (!dev->iommu->max_pasids) > return IOMMU_PASID_INVALID; > > /* > * max_pasids is set up by vendor driver based on number of > PASID bits > * supported but the IDA allocation is inclusive. > */ > ret = ida_alloc_range(&iommu_global_pasid_ida, > IOMMU_FIRST_GLOBAL_PASID, > dev->iommu->max_pasids - 1, GFP_KERNEL); > > return ret < 0 ? IOMMU_PASID_INVALID : ret; > } > EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); > good catch, sorry i missed this. let me send an updated version. > Other change in this series looks good to me. > > I hope I can queue this series including above change as part of my VT-d > update for v6.5 to Joerg if no objection. > > Let's try to re-enable this key feature of Intel idxd driver in v6.5. > > Best regards, > baolu Thanks, Jacob
diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index 9821bc44f5ac..b033cc415a00 100644 --- a/drivers/iommu/iommu-sva.c +++ b/drivers/iommu/iommu-sva.c @@ -10,33 +10,30 @@ #include "iommu-sva.h" static DEFINE_MUTEX(iommu_sva_lock); -static DEFINE_IDA(iommu_global_pasid_ida); /* Allocate a PASID for the mm within range (inclusive) */ -static int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t max) +static int iommu_sva_alloc_pasid(struct mm_struct *mm, struct device *dev) { + ioasid_t pasid; int ret = 0; - if (min == IOMMU_PASID_INVALID || - max == IOMMU_PASID_INVALID || - min == 0 || max < min) - return -EINVAL; - if (!arch_pgtable_dma_compat(mm)) return -EBUSY; mutex_lock(&iommu_sva_lock); /* Is a PASID already associated with this mm? */ if (mm_valid_pasid(mm)) { - if (mm->pasid < min || mm->pasid > max) + if (mm->pasid >= dev->iommu->max_pasids) ret = -EOVERFLOW; goto out; } - ret = ida_alloc_range(&iommu_global_pasid_ida, min, max, GFP_KERNEL); - if (ret < min) + pasid = iommu_alloc_global_pasid_dev(dev); + if (pasid == IOMMU_PASID_INVALID) { + ret = -ENOSPC; goto out; - mm->pasid = ret; + } + mm->pasid = pasid; ret = 0; out: mutex_unlock(&iommu_sva_lock); @@ -63,15 +60,10 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm { struct iommu_domain *domain; struct iommu_sva *handle; - ioasid_t max_pasids; int ret; - max_pasids = dev->iommu->max_pasids; - if (!max_pasids) - return ERR_PTR(-EOPNOTSUPP); - /* Allocate mm->pasid if necessary. */ - ret = iommu_sva_alloc_pasid(mm, 1, max_pasids - 1); + ret = iommu_sva_alloc_pasid(mm, dev); if (ret) return ERR_PTR(ret); @@ -216,5 +208,5 @@ void mm_pasid_drop(struct mm_struct *mm) if (likely(!mm_valid_pasid(mm))) return; - ida_free(&iommu_global_pasid_ida, mm->pasid); + iommu_free_global_pasid(mm->pasid); } diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index f1dcfa3f1a1b..d4f9ab210d6b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -39,6 +39,7 @@ static struct kset *iommu_group_kset; static DEFINE_IDA(iommu_group_ida); +static DEFINE_IDA(iommu_global_pasid_ida); static unsigned int iommu_def_domain_type __read_mostly; static bool iommu_dma_strict __read_mostly = IS_ENABLED(CONFIG_IOMMU_DEFAULT_DMA_STRICT); @@ -3393,3 +3394,30 @@ struct iommu_domain *iommu_sva_domain_alloc(struct device *dev, return domain; } + +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) +{ + int ret; + ioasid_t max; + + max = dev->iommu->max_pasids; + /* + * max_pasids is set up by vendor driver based on number of PASID bits + * supported but the IDA allocation is inclusive. + */ + ret = ida_alloc_range(&iommu_global_pasid_ida, IOMMU_FIRST_GLOBAL_PASID, max - 1, GFP_KERNEL); + if (ret < 0) + return IOMMU_PASID_INVALID; + + return ret; +} +EXPORT_SYMBOL_GPL(iommu_alloc_global_pasid_dev); + +void iommu_free_global_pasid(ioasid_t pasid) +{ + if (WARN_ON(pasid == IOMMU_PASID_INVALID)) + return; + + ida_free(&iommu_global_pasid_ida, pasid); +} +EXPORT_SYMBOL_GPL(iommu_free_global_pasid); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index c714d659d114..f7bfe03bda19 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -191,6 +191,7 @@ enum iommu_dev_features { }; #define IOMMU_NO_PASID (0U) /* Reserved for DMA w/o PASID */ +#define IOMMU_FIRST_GLOBAL_PASID (1U) /*starting range for allocation */ #define IOMMU_PASID_INVALID (-1U) typedef unsigned int ioasid_t; @@ -722,6 +723,8 @@ void iommu_detach_device_pasid(struct iommu_domain *domain, struct iommu_domain * iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid, unsigned int type); +ioasid_t iommu_alloc_global_pasid_dev(struct device *dev); +void iommu_free_global_pasid(ioasid_t pasid); #else /* CONFIG_IOMMU_API */ struct iommu_ops {}; @@ -1083,6 +1086,13 @@ iommu_get_domain_for_dev_pasid(struct device *dev, ioasid_t pasid, { return NULL; } + +static inline ioasid_t iommu_alloc_global_pasid_dev(struct device *dev) +{ + return IOMMU_PASID_INVALID; +} + +static inline void iommu_free_global_pasid(ioasid_t pasid) {} #endif /* CONFIG_IOMMU_API */ /**