[GIT PULL] dma-mapping fix for Linux 5.19

2022-06-25 Thread Christoph Hellwig
The following changes since commit a111daf0c53ae91e71fd2bfe7497862d14132e3e:

  Linux 5.19-rc3 (2022-06-19 15:06:47 -0500)

are available in the Git repository at:

  git://git.infradead.org/users/hch/dma-mapping.git 
tags/dma-mapping-5.19-2022-06-26

for you to fetch changes up to 3be4562584bba603f33863a00c1c32eecf772ee6:

  dma-direct: use the correct size for dma_set_encrypted() (2022-06-23 15:26:59 
+0200)


dma-mapping fixes for Linux 5.19

 - pass the correct size to dma_set_encrypted() when freeing memory
   (Dexuan Cui)


Dexuan Cui (1):
  dma-direct: use the correct size for dma_set_encrypted()

 kernel/dma/direct.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 3/3] arch/*/: remove CONFIG_VIRT_TO_BUS

2022-06-25 Thread Michael Schmitz

Arnd,

Am 24.06.2022 um 21:10 schrieb Arnd Bergmann:

On Sat, Jun 18, 2022 at 3:06 AM Michael Schmitz  wrote:

Am 18.06.2022 um 00:57 schrieb Arnd Bergmann:


All architecture-independent users of virt_to_bus() and bus_to_virt()
have been fixed to use the dma mapping interfaces or have been
removed now.  This means the definitions on most architectures, and the
CONFIG_VIRT_TO_BUS symbol are now obsolete and can be removed.

The only exceptions to this are a few network and scsi drivers for m68k
Amiga and VME machines and ppc32 Macintosh. These drivers work correctly
with the old interfaces and are probably not worth changing.


The Amiga SCSI drivers are all old WD33C93 ones, and replacing
virt_to_bus by virt_to_phys in the dma_setup() function there would
cause no functional change at all.


Ok, thanks for taking a look here.


drivers/vme/bridges/vme_ca91cx42.c hasn't been used at all on m68k (it
is a PCI-to-VME bridge chipset driver that would be needed on
architectures that natively use a PCI bus). I haven't found anything
that selects that driver, so not sure it is even still in use??


It's gone now, Greg has already taken my patches for this through
the staging tree.


One less to worry about, thanks.


That would allow you to drop the remaining virt_to_bus define from
arch/m68k/include/asm/virtconvert.h.

I could submit a patch to convert the Amiga SCSI drivers to use
virt_to_phys if Geert and the SCSI maintainers think it's worth the churn.


I don't think using virt_to_phys() is an improvement here, as
virt_to_bus() was originally meant as a better abstraction to
replace the use of virt_to_phys() to make drivers portable, before
it got replaced by the dma-mapping interface in turn.

It looks like the Amiga SCSI drivers have an open-coded version of
what dma_map_single() does, to do bounce buffering and cache
management. The ideal solution would be to convert the drivers
actually use the appropriate dma-mapping interfaces and remove
this custom code.


I've taken another look at these drivers' dma_setup() functions and they 
all look much more complex than the Amiga ESP drivers (which do use the 
dma-mapping interface for parts of the DMA setup). From my limited 
understanding, the difference between the ESP and WD33C93 drivers is 
that the former are used on 040/060 accelerator boards only (where the 
processor does do bus snooping and DMA can access all of RAM). The 
latter ones would need cache management, could only use non-coherent 
mappings and would require special case handling for DMA-inaccessible 
RAM inside a device-specific dma ops' map_page() function.


That's several bridges too far for me ... I have no Amiga hardware 
whatsoever, and know no one who could test changes to WD33C93 drivers 
for me.


What I have is a NCR5380 with the proverbial 'pathological DMA' 
integration example (and its driver was never changed to even use 
virt_to_bus()!). I might learn enough about using the dma-mapping API on 
that one eventually (though the requirement for at least 1 MB swiotlb 
bounce buffers looks hard to meet), and use that to convert the WD33C93 
drivers, but it would still remain untested.


> The same could be done for the two vme drivers (scsi/mvme147.c

and ethernet/82596.c), which do the cache management but
apparently don't need swiotlb bounce buffering.

Rewriting the drivers to modern APIs is of course non-trivial,
and if you want a shortcut here, I would suggest introducing
platform specific helpers similar to isa_virt_to_bus() and call
them amiga_virt_to_bus() and vme_virt_to_bus, respectively.


I don't think Amiga and m68k VME differ at all in that respect, so might 
just call it m68k_virt_to_bus() for now.



Putting these into a platform specific header file at least helps
clarify that both the helper functions and the drivers using them
are non-portable.


There are no platform specific header files other than asm/amigahw.h and 
asm/mvme147hw.h, currently only holding register address definitions. 
Would it be OK to add m68k_virt_to_bus() in there if it can't remain in 
asm/virtconvert.h, Geert?





32bit powerpc is a different matter though.


It's similar, but unrelated. The two apple ethernet drivers
(bmac and mace) can again either get changed to use the
dma-mapping interfaces, or get a custom pmac_virt_to_bus()/
pmac_bus_to_virt() helper.


Hmmm - I see Finn had done the DMA API conversion on macmace.c which 
might give some hints on what to do about mace.c ... no idea about 
bmac.c though. And again, haven't got hardware to test, so custom 
helpers is it, then.


Cheers,

Michael


There is also drivers/tty/serial/cpm_uart/cpm_uart_cpm2.c,
which I think just needs a trivial change, but I'm not sure
how to do it correctly.

  Arnd


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v9 00/11] iommu: SVA and IOPF refactoring

2022-06-25 Thread Baolu Lu

Hi folks,

On 2022/6/21 22:43, Lu Baolu wrote:

Hi folks,

The former part of this series refactors the IOMMU SVA code by assigning
an SVA type of iommu_domain to a shared virtual address and replacing
sva_bind/unbind iommu ops with set/block_dev_pasid domain ops.

The latter part changes the existing I/O page fault handling framework
from only serving SVA to a generic one. Any driver or component could
handle the I/O page faults for its domain in its own way by installing
an I/O page fault handler.

This series has been functionally tested on an x86 machine and compile
tested for all architectures.

This series is also available on github:
[2]https://github.com/LuBaolu/intel-iommu/commits/iommu-sva-refactoring-v9

Please review and suggest.


Just a gentle ping on this series.

Do you have further inputs? I am trying to see if we can merge this
series for v5.20. The drivers also depend on it to enable their kernel
DMA with PASID.

Sorry to disturb you.

Best regards,
baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: iommu_sva_bind_device question

2022-06-25 Thread Jerry Snitselaar
On Sat, Jun 25, 2022 at 12:52:27PM -0700, Fenghua Yu wrote:
> Hi, Jerry and Baolu,
> 
> On Fri, Jun 24, 2022 at 07:47:30AM -0700, Jerry Snitselaar wrote:
> > > > > > > Hi Baolu & Dave,
> > > > > fails.
> > > > > 
> > > > > You also will get the following warning if you don't have scalable
> > > > > mode enabled (either not enabled by default, or if enabled by default
> > > > > and passed intel_iommu=on,sm_off):
> > > > 
> > > > If scalable mode is disabled, iommu_dev_enable_feature(IOMMU_SVA) will
> > > > return failure, hence driver should not call iommu_sva_bind_device().
> > > > I guess below will disappear if above is fixed in the idxd driver.
> 
> Yes, Jerry's patch fixes the WARNING as well.
> 
> > > > 
> > > > Best regards,
> > > > baolu
> > > >
> > > 
> > > It looks like there was a recent maintainer change, and Fenghua is now
> > > the maintainer. Fenghua thoughts on this? With 42a1b73852c4
> > > ("dmaengine: idxd: Separate user and kernel pasid enabling") the code
> > > no longer depends on iommu_dev_feature_enable succeeding. Testing with
> > > something like this works (ran dmatest without sm_on, and
> > > dsa_user_test_runner.sh with sm_on, plus booting with various
> > > intel_iommu= combinations):
> > > 
> > > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
> > > index 355fb3ef4cbf..5b49fd5c1e25 100644
> > > --- a/drivers/dma/idxd/init.c
> > > +++ b/drivers/dma/idxd/init.c
> > > @@ -514,13 +514,14 @@ static int idxd_probe(struct idxd_device *idxd)
> > > if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) {
> > > if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA))
> > > dev_warn(dev, "Unable to turn on user SVA 
> > > feature.\n");
> > > -   else
> > > +   else {
> > > set_bit(IDXD_FLAG_USER_PASID_ENABLED, 
> > > >flags);
> > > 
> > > -   if (idxd_enable_system_pasid(idxd))
> 
> Please add "{" after this if.
> 
> > > -   dev_warn(dev, "No in-kernel DMA with PASID.\n");
> > > -   else
> then "}" before this else.
> 
> > > -   set_bit(IDXD_FLAG_PASID_ENABLED, >flags);
> > > +   if (idxd_enable_system_pasid(idxd))
> > > +   dev_warn(dev, "No in-kernel DMA with 
> > > PASID.\n");
> > > +   else
> > > +   set_bit(IDXD_FLAG_PASID_ENABLED, 
> > > >flags);
> > > +   }
> > > } else if (!sva) {
> > > dev_warn(dev, "User forced SVA off via module param.\n");
> > > }
> 
> The patch was copied/pasted here. So the tabs are lost at beginning of each
> line. So it cannot be applied. Please change the tabs back.
> 
> Could you please send this patch in a separate email so that it has a
> right patch format and description and ready to be picked up?
> 

Sure, if you feel this is the correct solution. Just to be clear you would
like the end result to be:

if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) {
if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA))
dev_warn(dev, "Unable to turn on user SVA feature.\n");
else {
set_bit(IDXD_FLAG_USER_PASID_ENABLED, >flags);

if (idxd_enable_system_pasid(idxd)) {
dev_warn(dev, "No in-kernel DMA with PASID.\n");
} else
set_bit(IDXD_FLAG_PASID_ENABLED, >flags);
}
} else if (!sva) {
dev_warn(dev, "User forced SVA off via module param.\n");
}


> > > 
> > > The commit description is a bit confusing, because it talks about there
> > > being no dependency, but ties user pasid to enabling/disabling the SVA
> > > feature, which system pasid would depend on as well.
> > > 
> > > Regards,
> > > Jerry
> > 
> > Things like that warning message "Unable to turn on user SVA feature" when
> > iommu_dev_enable_feature fails though seems to be misleading with user
> > inserted in there. I'll leave it to the idxd folks to figure out.
> 
> How about removing "user" from the warning message? So the message will
> be "Unable to turn on SVA feature"?
>

I think what was confusing to me is it seemed to tie the SVA iommu
feature to the user, and talked about independence of the kernel and
user pasids. I understand the pasids themselves being independent, but
both depend on the SVA feature being enabled. So idxd_enable_system_pasid
can only happen if iommu_dev_feature_enable(dev, IOMMU_DEV_FEAT_SVA)
has succeeded prior to it, and idxd_disable_system_pasid should be
called if needed before there is a call to
iommu_dev_feature_disable(dev, IOMMU_DEV_FEAT_SVA).

When I looked at the code that seemed to be the case outside of this
block in idxd_probe, but I wasn't sure if I was missing something else.

Regards,
Jerry

> Thanks.
> 
> -Fenghua


Re: iommu_sva_bind_device question

2022-06-25 Thread Fenghua Yu
Hi, Jerry and Baolu,

On Fri, Jun 24, 2022 at 07:47:30AM -0700, Jerry Snitselaar wrote:
> > > > > > Hi Baolu & Dave,
> > > > fails.
> > > > 
> > > > You also will get the following warning if you don't have scalable
> > > > mode enabled (either not enabled by default, or if enabled by default
> > > > and passed intel_iommu=on,sm_off):
> > > 
> > > If scalable mode is disabled, iommu_dev_enable_feature(IOMMU_SVA) will
> > > return failure, hence driver should not call iommu_sva_bind_device().
> > > I guess below will disappear if above is fixed in the idxd driver.

Yes, Jerry's patch fixes the WARNING as well.

> > > 
> > > Best regards,
> > > baolu
> > >
> > 
> > It looks like there was a recent maintainer change, and Fenghua is now
> > the maintainer. Fenghua thoughts on this? With 42a1b73852c4
> > ("dmaengine: idxd: Separate user and kernel pasid enabling") the code
> > no longer depends on iommu_dev_feature_enable succeeding. Testing with
> > something like this works (ran dmatest without sm_on, and
> > dsa_user_test_runner.sh with sm_on, plus booting with various
> > intel_iommu= combinations):
> > 
> > diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
> > index 355fb3ef4cbf..5b49fd5c1e25 100644
> > --- a/drivers/dma/idxd/init.c
> > +++ b/drivers/dma/idxd/init.c
> > @@ -514,13 +514,14 @@ static int idxd_probe(struct idxd_device *idxd)
> > if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) {
> > if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA))
> > dev_warn(dev, "Unable to turn on user SVA 
> > feature.\n");
> > -   else
> > +   else {
> > set_bit(IDXD_FLAG_USER_PASID_ENABLED, >flags);
> > 
> > -   if (idxd_enable_system_pasid(idxd))

Please add "{" after this if.

> > -   dev_warn(dev, "No in-kernel DMA with PASID.\n");
> > -   else
then "}" before this else.

> > -   set_bit(IDXD_FLAG_PASID_ENABLED, >flags);
> > +   if (idxd_enable_system_pasid(idxd))
> > +   dev_warn(dev, "No in-kernel DMA with 
> > PASID.\n");
> > +   else
> > +   set_bit(IDXD_FLAG_PASID_ENABLED, 
> > >flags);
> > +   }
> > } else if (!sva) {
> > dev_warn(dev, "User forced SVA off via module param.\n");
> > }

The patch was copied/pasted here. So the tabs are lost at beginning of each
line. So it cannot be applied. Please change the tabs back.

Could you please send this patch in a separate email so that it has a
right patch format and description and ready to be picked up?

> > 
> > The commit description is a bit confusing, because it talks about there
> > being no dependency, but ties user pasid to enabling/disabling the SVA
> > feature, which system pasid would depend on as well.
> > 
> > Regards,
> > Jerry
> 
> Things like that warning message "Unable to turn on user SVA feature" when
> iommu_dev_enable_feature fails though seems to be misleading with user
> inserted in there. I'll leave it to the idxd folks to figure out.

How about removing "user" from the warning message? So the message will
be "Unable to turn on SVA feature"?

Thanks.

-Fenghua
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 1/1] iommu/vt-d: Fix RID2PASID setup/teardown failure

2022-06-25 Thread Lu Baolu
The IOMMU driver shares the pasid table for PCI alias devices. When the
RID2PASID entry of the shared pasid table has been filled by the first
device, the subsequent device will encounter the "DMAR: Setup RID2PASID
failed" failure as the pasid entry has already been marked as present.
As the result, the IOMMU probing process will be aborted.

On the contrary, when any alias device is hot-removed from the system,
for example, by writing to /sys/bus/pci/devices/.../remove, the shared
RID2PASID will be cleared without any notifications to other devices.
As the result, any DMAs from those rest devices are blocked.

Sharing pasid table among PCI alias devices could save two memory pages
for devices underneath the PCIe-to-PCI bridges. Anyway, considering that
those devices are rare on modern platforms that support VT-d in scalable
mode and the saved memory is negligible, it's reasonable to remove this
part of immature code to make the driver feasible and stable.

Fixes: ef848b7e5a6a0 ("iommu/vt-d: Setup pasid entry for RID2PASID support")
Reported-by: Chenyi Qiang 
Reported-by: Ethan Zhao 
Signed-off-by: Lu Baolu 
Reviewed-by: Kevin Tian 
Reviewed-by: Ethan Zhao 
Cc: sta...@vger.kernel.org
Link: https://lore.kernel.org/r/20220623065720.727849-1-baolu...@linux.intel.com
---
 include/linux/intel-iommu.h |  3 --
 drivers/iommu/intel/pasid.h |  1 -
 drivers/iommu/intel/iommu.c | 24 -
 drivers/iommu/intel/pasid.c | 69 ++---
 4 files changed, 3 insertions(+), 94 deletions(-)

diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 4f29139bbfc3..5fcf89faa31a 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -612,7 +612,6 @@ struct intel_iommu {
 struct device_domain_info {
struct list_head link;  /* link to domain siblings */
struct list_head global; /* link to global list */
-   struct list_head table; /* link to pasid table */
u32 segment;/* PCI segment number */
u8 bus; /* PCI bus number */
u8 devfn;   /* PCI devfn number */
@@ -729,8 +728,6 @@ extern int dmar_ir_support(void);
 void *alloc_pgtable_page(int node);
 void free_pgtable_page(void *vaddr);
 struct intel_iommu *domain_get_iommu(struct dmar_domain *domain);
-int for_each_device_domain(int (*fn)(struct device_domain_info *info,
-void *data), void *data);
 void iommu_flush_write_buffer(struct intel_iommu *iommu);
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev);
 struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn);
diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
index 583ea67fc783..bf5b937848b4 100644
--- a/drivers/iommu/intel/pasid.h
+++ b/drivers/iommu/intel/pasid.h
@@ -74,7 +74,6 @@ struct pasid_table {
void*table; /* pasid table pointer */
int order;  /* page order of pasid table */
u32 max_pasid;  /* max pasid */
-   struct list_headdev;/* device list */
 };
 
 /* Get PRESENT bit of a PASID directory entry. */
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 44016594831d..5c0dce78586a 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -320,30 +320,6 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
 DEFINE_SPINLOCK(device_domain_lock);
 static LIST_HEAD(device_domain_list);
 
-/*
- * Iterate over elements in device_domain_list and call the specified
- * callback @fn against each element.
- */
-int for_each_device_domain(int (*fn)(struct device_domain_info *info,
-void *data), void *data)
-{
-   int ret = 0;
-   unsigned long flags;
-   struct device_domain_info *info;
-
-   spin_lock_irqsave(_domain_lock, flags);
-   list_for_each_entry(info, _domain_list, global) {
-   ret = fn(info, data);
-   if (ret) {
-   spin_unlock_irqrestore(_domain_lock, flags);
-   return ret;
-   }
-   }
-   spin_unlock_irqrestore(_domain_lock, flags);
-
-   return 0;
-}
-
 const struct iommu_ops intel_iommu_ops;
 
 static bool translation_pre_enabled(struct intel_iommu *iommu)
diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index cb4c1d0cf25c..17cad7c1f62d 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -86,54 +86,6 @@ void vcmd_free_pasid(struct intel_iommu *iommu, u32 pasid)
 /*
  * Per device pasid table management:
  */
-static inline void
-device_attach_pasid_table(struct device_domain_info *info,
- struct pasid_table *pasid_table)
-{
-   info->pasid_table = pasid_table;
-   list_add(>table, _table->dev);
-}
-
-static inline void
-device_detach_pasid_table(struct device_domain_info 

[PATCH 0/1] iommu/vt-d: Fixes for v5.19-rc4

2022-06-25 Thread Lu Baolu
Hi Joerg,

One fix is queued for v5.19. It aims to fix:

- RID2PASID setup/teardown failures for pci alias devices

Please consider it for the iommu/fix branch.

Best regards,
Lu Baolu

Lu Baolu (1):
  iommu/vt-d: Fix RID2PASID setup/teardown failure

 include/linux/intel-iommu.h |  3 --
 drivers/iommu/intel/pasid.h |  1 -
 drivers/iommu/intel/iommu.c | 24 -
 drivers/iommu/intel/pasid.c | 69 ++---
 4 files changed, 3 insertions(+), 94 deletions(-)

-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v1 6/6] iommu/vt-d: Make DMAR_UNITS_SUPPORTED default 1024

2022-06-25 Thread Lu Baolu
If the available hardware exceeds DMAR_UNITS_SUPPORTED (previously set
to MAX_IO_APICS, or 128), it causes these messages: "DMAR: Failed to
allocate seq_id", "DMAR: Parse DMAR table failure.", and "x2apic: IRQ
remapping doesn't support X2APIC mode x2apic disabled"; and the system
fails to boot properly.

To support up to 64 sockets with 10 DMAR units each (640), make the
value of DMAR_UNITS_SUPPORTED default 1024.

Signed-off-by: Steve Wahl
Signed-off-by: Lu Baolu 
---
 include/linux/dmar.h | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index cbd714a198a0..d81a51978d01 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -18,11 +18,7 @@
 
 struct acpi_dmar_header;
 
-#ifdef CONFIG_X86
-# define   DMAR_UNITS_SUPPORTEDMAX_IO_APICS
-#else
-# define   DMAR_UNITS_SUPPORTED64
-#endif
+#define DMAR_UNITS_SUPPORTED   1024
 
 /* DMAR Flags */
 #define DMAR_INTR_REMAP0x1
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v1 5/6] iommu/vt-d: Remove global g_iommus array

2022-06-25 Thread Lu Baolu
The g_iommus is not used anywhere. Remove it to avoid dead code.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.c | 42 -
 1 file changed, 42 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index f6d7055cffd7..9a284394b2c5 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -126,9 +126,6 @@ static inline unsigned long virt_to_dma_pfn(void *p)
return page_to_dma_pfn(virt_to_page(p));
 }
 
-/* global iommu list, set NULL for ignored DMAR units */
-static struct intel_iommu **g_iommus;
-
 static void __init check_tylersburg_isoch(void);
 static int rwbf_quirk;
 
@@ -287,9 +284,6 @@ static LIST_HEAD(dmar_satc_units);
 #define for_each_rmrr_units(rmrr) \
list_for_each_entry(rmrr, _rmrr_units, list)
 
-/* bitmap for indexing intel_iommus */
-static int g_num_of_iommus;
-
 static void dmar_remove_one_dev_info(struct device *dev);
 
 int dmar_disabled = !IS_ENABLED(CONFIG_INTEL_IOMMU_DEFAULT_ON);
@@ -1694,7 +1688,6 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
iommu->domain_ids = NULL;
}
 
-   g_iommus[iommu->seq_id] = NULL;
iommu->flags &= ~VTD_FLAG_IOMMU_PROBED;
 
/* free context mapping */
@@ -2899,36 +2892,6 @@ static int __init init_dmars(void)
struct intel_iommu *iommu;
int ret;
 
-   /*
-* for each drhd
-*allocate root
-*initialize and program root entry to not present
-* endfor
-*/
-   for_each_drhd_unit(drhd) {
-   /*
-* lock not needed as this is only incremented in the single
-* threaded kernel __init code path all other access are read
-* only
-*/
-   if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
-   g_num_of_iommus++;
-   continue;
-   }
-   pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
-   }
-
-   /* Preallocate enough resources for IOMMU hot-addition */
-   if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
-   g_num_of_iommus = DMAR_UNITS_SUPPORTED;
-
-   g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
-   GFP_KERNEL);
-   if (!g_iommus) {
-   ret = -ENOMEM;
-   goto error;
-   }
-
ret = intel_cap_audit(CAP_AUDIT_STATIC_DMAR, NULL);
if (ret)
goto free_iommu;
@@ -2951,7 +2914,6 @@ static int __init init_dmars(void)
   intel_pasid_max_id);
}
 
-   g_iommus[iommu->seq_id] = iommu;
iommu->flags |= VTD_FLAG_IOMMU_PROBED;
 
intel_iommu_init_qi(iommu);
@@ -3079,9 +3041,6 @@ static int __init init_dmars(void)
free_dmar_iommu(iommu);
}
 
-   kfree(g_iommus);
-
-error:
return ret;
 }
 
@@ -3488,7 +3447,6 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
if (iommu->gcmd & DMA_GCMD_TE)
iommu_disable_translation(iommu);
 
-   g_iommus[iommu->seq_id] = iommu;
iommu->flags |= VTD_FLAG_IOMMU_PROBED;
ret = iommu_init_domains(iommu);
if (ret == 0)
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v1 4/6] iommu/vt-d: Add VTD_FLAG_IOMMU_PROBED flag

2022-06-25 Thread Lu Baolu
In the IOMMU hot-add path, there's a need to check whether an IOMMU
has been probed. Instead of checking the IOMMU pointer in the global
list, it's better to allocate a flag bit in iommu->flags for this
purpose.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.h | 1 +
 drivers/iommu/intel/iommu.c | 5 -
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 56c3d1a9e155..105a1e7c60d9 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -479,6 +479,7 @@ enum {
 #define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0)
 #define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1)
 #define VTD_FLAG_SVM_CAPABLE   (1 << 2)
+#define VTD_FLAG_IOMMU_PROBED  (1 << 3)
 
 extern int intel_iommu_sm;
 
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 78b26fef685e..f6d7055cffd7 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1695,6 +1695,7 @@ static void free_dmar_iommu(struct intel_iommu *iommu)
}
 
g_iommus[iommu->seq_id] = NULL;
+   iommu->flags &= ~VTD_FLAG_IOMMU_PROBED;
 
/* free context mapping */
free_context_table(iommu);
@@ -2951,6 +2952,7 @@ static int __init init_dmars(void)
}
 
g_iommus[iommu->seq_id] = iommu;
+   iommu->flags |= VTD_FLAG_IOMMU_PROBED;
 
intel_iommu_init_qi(iommu);
 
@@ -3460,7 +3462,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
int sp, ret;
struct intel_iommu *iommu = dmaru->iommu;
 
-   if (g_iommus[iommu->seq_id])
+   if (iommu->flags & VTD_FLAG_IOMMU_PROBED)
return 0;
 
ret = intel_cap_audit(CAP_AUDIT_HOTPLUG_DMAR, iommu);
@@ -3487,6 +3489,7 @@ static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
iommu_disable_translation(iommu);
 
g_iommus[iommu->seq_id] = iommu;
+   iommu->flags |= VTD_FLAG_IOMMU_PROBED;
ret = iommu_init_domains(iommu);
if (ret == 0)
ret = iommu_alloc_root_entry(iommu);
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v1 3/6] iommu/vt-d: Refactor iommu information of each domain

2022-06-25 Thread Lu Baolu
When a DMA domain is attached to a device, it needs to allocate a domain
ID from its IOMMU. Currently, the domain ID information is stored in two
static arrays embedded in the domain structure. This can lead to memory
waste when the driver is running on a small platform.

This optimizes these static arrays by replacing them with an xarray and
consuming memory on demand.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.h |  27 +---
 drivers/iommu/intel/iommu.c | 123 
 drivers/iommu/intel/pasid.c |   2 +-
 drivers/iommu/intel/svm.c   |   2 +-
 4 files changed, 90 insertions(+), 64 deletions(-)

diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 56e0d8cd2102..56c3d1a9e155 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -524,17 +525,15 @@ struct context_entry {
  */
 #define DOMAIN_FLAG_USE_FIRST_LEVELBIT(1)
 
+struct iommu_domain_info {
+   struct intel_iommu *iommu;
+   unsigned int refcnt;
+   u16 did;
+};
+
 struct dmar_domain {
int nid;/* node id */
-
-   unsigned int iommu_refcnt[DMAR_UNITS_SUPPORTED];
-   /* Refcount of devices per iommu */
-
-
-   u16 iommu_did[DMAR_UNITS_SUPPORTED];
-   /* Domain ids per IOMMU. Use u16 since
-* domain ids are 16 bit wide according
-* to VT-d spec, section 9.3 */
+   struct xarray iommu_array;  /* Attached IOMMU array */
 
u8 has_iotlb_device: 1;
u8 iommu_coherency: 1;  /* indicate coherency of iommu access */
@@ -640,6 +639,16 @@ static inline struct dmar_domain *to_dmar_domain(struct 
iommu_domain *dom)
return container_of(dom, struct dmar_domain, domain);
 }
 
+/* Retrieve the domain ID which has allocated to the domain */
+static inline u16
+domain_id_iommu(struct dmar_domain *domain, struct intel_iommu *iommu)
+{
+   struct iommu_domain_info *info =
+   xa_load(>iommu_array, iommu->seq_id);
+
+   return info->did;
+}
+
 /*
  * 0: readable
  * 1: writable
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 781e060352e6..78b26fef685e 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -254,10 +254,6 @@ static inline void context_clear_entry(struct 
context_entry *context)
 static struct dmar_domain *si_domain;
 static int hw_pass_through = 1;
 
-#define for_each_domain_iommu(idx, domain) \
-   for (idx = 0; idx < g_num_of_iommus; idx++) \
-   if (domain->iommu_refcnt[idx])
-
 struct dmar_rmrr_unit {
struct list_head list;  /* list of rmrr units   */
struct acpi_dmar_header *hdr;   /* ACPI header  */
@@ -453,16 +449,16 @@ static inline bool 
iommu_paging_structure_coherency(struct intel_iommu *iommu)
 
 static void domain_update_iommu_coherency(struct dmar_domain *domain)
 {
+   struct iommu_domain_info *info;
struct dmar_drhd_unit *drhd;
struct intel_iommu *iommu;
bool found = false;
-   int i;
+   unsigned long i;
 
domain->iommu_coherency = true;
-
-   for_each_domain_iommu(i, domain) {
+   xa_for_each(>iommu_array, i, info) {
found = true;
-   if (!iommu_paging_structure_coherency(g_iommus[i])) {
+   if (!iommu_paging_structure_coherency(info->iommu)) {
domain->iommu_coherency = false;
break;
}
@@ -1495,7 +1491,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu 
*iommu,
unsigned int aligned_pages = __roundup_pow_of_two(pages);
unsigned int mask = ilog2(aligned_pages);
uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
-   u16 did = domain->iommu_did[iommu->seq_id];
+   u16 did = domain_id_iommu(domain, iommu);
 
BUG_ON(pages == 0);
 
@@ -1565,11 +1561,12 @@ static inline void __mapping_notify_one(struct 
intel_iommu *iommu,
 static void intel_flush_iotlb_all(struct iommu_domain *domain)
 {
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
-   int idx;
+   struct iommu_domain_info *info;
+   unsigned long idx;
 
-   for_each_domain_iommu(idx, dmar_domain) {
-   struct intel_iommu *iommu = g_iommus[idx];
-   u16 did = dmar_domain->iommu_did[iommu->seq_id];
+   xa_for_each(_domain->iommu_array, idx, info) {
+   struct intel_iommu *iommu = info->iommu;
+   u16 did = domain_id_iommu(dmar_domain, iommu);
 
if (domain_use_first_level(dmar_domain))
qi_flush_piotlb(iommu, did, PASID_RID2PASID, 0, -1, 0);
@@ -1745,6 +1742,7 @@ static struct 

[PATCH v1 1/6] iommu/vt-d: Remove unused domain_get_iommu()

2022-06-25 Thread Lu Baolu
It is not used anywhere. Remove it to avoid dead code.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.h |  1 -
 drivers/iommu/intel/iommu.c | 18 --
 2 files changed, 19 deletions(-)

diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index df64d3d9c49a..56e0d8cd2102 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -725,7 +725,6 @@ extern int dmar_ir_support(void);
 
 void *alloc_pgtable_page(int node);
 void free_pgtable_page(void *vaddr);
-struct intel_iommu *domain_get_iommu(struct dmar_domain *domain);
 void iommu_flush_write_buffer(struct intel_iommu *iommu);
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev);
 struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn);
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index da6cfea0f0d6..781e060352e6 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -445,24 +445,6 @@ int iommu_calculate_agaw(struct intel_iommu *iommu)
return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
 }
 
-/* This functionin only returns single iommu in a domain */
-struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
-{
-   int iommu_id;
-
-   /* si_domain and vm domain should not get here. */
-   if (WARN_ON(!iommu_is_dma_domain(>domain)))
-   return NULL;
-
-   for_each_domain_iommu(iommu_id, domain)
-   break;
-
-   if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
-   return NULL;
-
-   return g_iommus[iommu_id];
-}
-
 static inline bool iommu_paging_structure_coherency(struct intel_iommu *iommu)
 {
return sm_supported(iommu) ?
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v1 2/6] iommu/vt-d: Use IDA interface to manage iommu sequence id

2022-06-25 Thread Lu Baolu
Switch dmar unit sequence id allocation and release from bitmap to IDA
interface.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/dmar.c | 33 +++--
 1 file changed, 7 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 2a5e0f91e647..bf43889b9d2a 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -60,7 +60,7 @@ LIST_HEAD(dmar_drhd_units);
 
 struct acpi_table_header * __initdata dmar_tbl;
 static int dmar_dev_scope_status = 1;
-static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
+static DEFINE_IDA(dmar_seq_ids);
 
 static int alloc_iommu(struct dmar_drhd_unit *drhd);
 static void free_iommu(struct intel_iommu *iommu);
@@ -1023,28 +1023,6 @@ static int map_iommu(struct intel_iommu *iommu, u64 
phys_addr)
return err;
 }
 
-static int dmar_alloc_seq_id(struct intel_iommu *iommu)
-{
-   iommu->seq_id = find_first_zero_bit(dmar_seq_ids,
-   DMAR_UNITS_SUPPORTED);
-   if (iommu->seq_id >= DMAR_UNITS_SUPPORTED) {
-   iommu->seq_id = -1;
-   } else {
-   set_bit(iommu->seq_id, dmar_seq_ids);
-   sprintf(iommu->name, "dmar%d", iommu->seq_id);
-   }
-
-   return iommu->seq_id;
-}
-
-static void dmar_free_seq_id(struct intel_iommu *iommu)
-{
-   if (iommu->seq_id >= 0) {
-   clear_bit(iommu->seq_id, dmar_seq_ids);
-   iommu->seq_id = -1;
-   }
-}
-
 static int alloc_iommu(struct dmar_drhd_unit *drhd)
 {
struct intel_iommu *iommu;
@@ -1062,11 +1040,14 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
if (!iommu)
return -ENOMEM;
 
-   if (dmar_alloc_seq_id(iommu) < 0) {
+   iommu->seq_id = ida_alloc_range(_seq_ids, 0,
+   DMAR_UNITS_SUPPORTED, GFP_KERNEL);
+   if (iommu->seq_id < 0) {
pr_err("Failed to allocate seq_id\n");
err = -ENOSPC;
goto error;
}
+   sprintf(iommu->name, "dmar%d", iommu->seq_id);
 
err = map_iommu(iommu, drhd->reg_base_addr);
if (err) {
@@ -1150,7 +1131,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
 err_unmap:
unmap_iommu(iommu);
 error_free_seq_id:
-   dmar_free_seq_id(iommu);
+   ida_free(_seq_ids, iommu->seq_id);
 error:
kfree(iommu);
return err;
@@ -1183,7 +1164,7 @@ static void free_iommu(struct intel_iommu *iommu)
if (iommu->reg)
unmap_iommu(iommu);
 
-   dmar_free_seq_id(iommu);
+   ida_free(_seq_ids, iommu->seq_id);
kfree(iommu);
 }
 
-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v1 0/6] iommu/vt-d: Reset DMAR_UNITS_SUPPORTED

2022-06-25 Thread Lu Baolu
Hi folks,

This is a follow-up series of changes proposed by this patch:

https://lore.kernel.org/linux-iommu/20220615183650.32075-1-steve.w...@hpe.com/

It removes several static arrays of size DMAR_UNITS_SUPPORTED and sets
the DMAR_UNITS_SUPPORTED to 1024.

Please help review and suggest.

Best regards,
baolu

Lu Baolu (6):
  iommu/vt-d: Remove unused domain_get_iommu()
  iommu/vt-d: Use IDA interface to manage iommu sequence id
  iommu/vt-d: Refactor iommu information of each domain
  iommu/vt-d: Add VTD_FLAG_IOMMU_PROBED flag
  iommu/vt-d: Remove global g_iommus array
  iommu/vt-d: Make DMAR_UNITS_SUPPORTED default 1024

 include/linux/dmar.h|   6 +-
 drivers/iommu/intel/iommu.h |  29 --
 drivers/iommu/intel/dmar.c  |  33 ++-
 drivers/iommu/intel/iommu.c | 188 ++--
 drivers/iommu/intel/pasid.c |   2 +-
 drivers/iommu/intel/svm.c   |   2 +-
 6 files changed, 103 insertions(+), 157 deletions(-)

-- 
2.25.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu