Re: [PATCH 0/5] iommu/amd: fixes for suspend/resume

2022-01-25 Thread Maxim Levitsky
On Tue, 2022-01-25 at 23:25 +, Mike Lothian wrote:
> On Tue, 25 Jan 2022 at 19:26, Maxim Levitsky  wrote:
> > Could you just apply these patches on top of 5.15 kernel and see if you get 
> > the warning?
> > 
> > If something could case it is I think patch 1, it does move the GA log 
> > enabled
> > to be a bit later.
> > I also added few warnings there. I wonder why your dmesg quote doesn't 
> > contain the C line
> > where the warning happens.
> > 
> > In partucular I added:
> > 
> > if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK)))
> > 
> > That will fire if GA log is already running (maybe BIOS enabled it? - it 
> > really shouldn't do that)
> > 
> > 
> > And that:
> > 
> > if (WARN_ON(i >= LOOP_TIMEOUT))
> > 
> > also should not happen and worth to be logged IMHO.
> > 
> > Best regards,
> > Maxim Levitsky
> > 
> 
> Hi
> 
> I applied on top of another kernel as you asked, I also enabled some debugging
> 
> [0.398833] [ cut here ]
> [0.398835] WARNING: CPU: 0 PID: 1 at drivers/iommu/amd/init.c:839
> amd_iommu_enable_interrupts+0x1da/0x440
> [0.398840] Modules linked in:
> [0.398841] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.16.0-rc5-agd5f+ 
> #1388
> [0.398843] Hardware name: ASUSTeK COMPUTER INC. ROG Strix
> G513QY_G513QY/G513QY, BIOS G513QY.316 11/29/2021
> [0.398845] RIP: 0010:amd_iommu_enable_interrupts+0x1da/0x440
> [0.398847] Code: 4b 38 48 89 41 18 b8 a0 86 01 00 0f 1f 44 00 00
> 48 8b 4b 38 8b 89 20 20 00 00 f7 c1 00 01 00 00 0f 85 7a fe ff ff ff
> c8 75 e6 <0f> 0b e9 6f fe ff ff 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44
> 0
> 0 00
> [0.398850] RSP: 0018:888100927c68 EFLAGS: 00010246
> [0.398851] RAX:  RBX: 88810004b000 RCX: 
> 0018
> [0.398853] RDX: 0008 RSI: 888100927c70 RDI: 
> c90800f0
> [0.398854] RBP: 888100927c68 R08: 8881015b8f88 R09: 
> 
> [0.398855] R10:  R11:  R12: 
> 7fff
> [0.398856] R13: 777f8000 R14:  R15: 
> 8357a758
> [0.398858] FS:  () GS:888fde40()
> knlGS:
> [0.398859] CS:  0010 DS:  ES:  CR0: 80050033
> [0.398860] CR2:  CR3: ac40c000 CR4: 
> 00150ef0
> [0.398862] Call Trace:
> [0.398864]  
> [0.398864]  ? iommu_setup+0x29a/0x29a
> [0.398867]  ? state_next+0x6e/0x1c9
> [0.398870]  ? iommu_setup+0x29a/0x29a
> [0.398872]  ? iommu_go_to_state+0x1f/0x33
> [0.398873]  ? amd_iommu_init+0xa/0x23
> [0.398875]  ? pci_iommu_init+0xf/0x45
> [0.398876]  ? iommu_setup+0x29a/0x29a
> [0.398878]  ? 
> __initstub__kmod_pci_dma__244_136_pci_iommu_initrootfs+0x5/0x8
> [0.398880]  ? do_one_initcall+0x100/0x290
> [0.398882]  ? do_initcall_level+0x8b/0xe5
> [0.398884]  ? do_initcalls+0x44/0x6d
> [0.398885]  ? kernel_init_freeable+0xc7/0x10d
> [0.398886]  ? rest_init+0xc0/0xc0
> [0.39]  ? kernel_init+0x11/0x150
> [0.398889]  ? ret_from_fork+0x22/0x30
> [0.398891]  
> [0.398892] ---[ end trace f048a4ec907dc976 ]---
> 
> Which points to patch one and "if (WARN_ON(i >= LOOP_TIMEOUT))"


Could you post the whole dmesg, or at least:

dmesg | grep AMD-Vi


What CPU does your system have?

I suspect that your system doesn't GA log feature enabled in the IOMMU, and the 
code never checks
for that, and here it fails enabling it, which  before my patches was just
ignoring it silently.


Best regards,
Maxim Levitsky
> 
> Hope that helps
> 
> Mike
> 


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


Re: [PATCH 0/7] iommu cleanup and refactoring

2022-01-25 Thread Lu Baolu

On 1/25/22 11:16 PM, Jason Gunthorpe wrote:

On Tue, Jan 25, 2022 at 02:48:02PM +, Robin Murphy wrote:
  

Agreed, certainly an IOMMU_DOMAIN_SVA type that can both encapsulate the mm
and effectively replace iommu_sva seems like a logical and fairly small next
step. We already have the paradigm of different domain types supporting
different ops, so initially an SVA domain would simply allow bind/unbind
rather than attach/detach/map/unmap.


I hope we can quickly get to a PASID enabled generic attach/detach
scheme - we really need this to do the uAPI part of this interface.


Agreed. Jacob is working on kernel DMA with PASID. He needs such
interfaces as well. I have worked out an implementation for vt-d driver.
It could be post for review inside Jacob's series for kernel DMA with
PASID.




they are fundamentally different things in their own right, and the ideal
API should give us the orthogonality to also bind a device to an SVA domain
without PASID (e.g. for KVM stage 2, or userspace assignment of simpler
fault/stall-tolerant devices), or attach PASIDs to regular iommu_domains.


Yes, these are orthogonal things. A iommu driver that supports PASID
ideally should support PASID enabled attach/detatch for every
iommu_domain type it supports.

SVA should not be entangled with PASID beyond that SVA is often used
with PASID - a SVA iommu_domain should be fully usable with a RID too.


The prototype of PASID enabled attach/detach ops could look like:

   int (*attach_dev_pasid)(struct iommu_domain *domain,
   struct device *dev, ioasid_t id);
   void (*detach_dev_pasid)(struct iommu_domain *domain,
struct device *dev, ioasid_t id);

But the iommu driver should implement different callbacks for

1) attaching an IOMMU DMA domain to a PASID on device;
   - kernel DMA with PASID
   - mdev-like device passthrough
   - etc.
2) attaching a CPU-shared domain to a PASID on device;
   - SVA
   - guest PASID
   - etc.



I'm hoping to see the core iommu code provide some simplified "SVA"
API that under the covers creates a SVA domain and then does a normal
PASID attach using the global PASID in the mm_struct - the
driver should not care what, or even if, PASID is used for a SVA
domain.

Jason



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


Re: [PATCH v2] iommu/vt-d: Fix PCI bus rescan device hot add

2022-01-25 Thread Lu Baolu

Hi Jacob,

On 1/26/22 2:57 AM, Jacob Pan wrote:

Hi all,

Just wondering if there are any other comments? This fixes a
regression that can cause system hang.


This looks fine to me. I will queue it for v5.17 if there's no further
comments.

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


Re: [PATCH 0/5] iommu/amd: fixes for suspend/resume

2022-01-25 Thread Mike Lothian
On Tue, 25 Jan 2022 at 19:26, Maxim Levitsky  wrote:
>
> Could you just apply these patches on top of 5.15 kernel and see if you get 
> the warning?
>
> If something could case it is I think patch 1, it does move the GA log enabled
> to be a bit later.
> I also added few warnings there. I wonder why your dmesg quote doesn't 
> contain the C line
> where the warning happens.
>
> In partucular I added:
>
> if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK)))
>
> That will fire if GA log is already running (maybe BIOS enabled it? - it 
> really shouldn't do that)
>
>
> And that:
>
> if (WARN_ON(i >= LOOP_TIMEOUT))
>
> also should not happen and worth to be logged IMHO.
>
> Best regards,
> Maxim Levitsky
>

Hi

I applied on top of another kernel as you asked, I also enabled some debugging

[0.398833] [ cut here ]
[0.398835] WARNING: CPU: 0 PID: 1 at drivers/iommu/amd/init.c:839
amd_iommu_enable_interrupts+0x1da/0x440
[0.398840] Modules linked in:
[0.398841] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.16.0-rc5-agd5f+ #1388
[0.398843] Hardware name: ASUSTeK COMPUTER INC. ROG Strix
G513QY_G513QY/G513QY, BIOS G513QY.316 11/29/2021
[0.398845] RIP: 0010:amd_iommu_enable_interrupts+0x1da/0x440
[0.398847] Code: 4b 38 48 89 41 18 b8 a0 86 01 00 0f 1f 44 00 00
48 8b 4b 38 8b 89 20 20 00 00 f7 c1 00 01 00 00 0f 85 7a fe ff ff ff
c8 75 e6 <0f> 0b e9 6f fe ff ff 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44
0
0 00
[0.398850] RSP: 0018:888100927c68 EFLAGS: 00010246
[0.398851] RAX:  RBX: 88810004b000 RCX: 0018
[0.398853] RDX: 0008 RSI: 888100927c70 RDI: c90800f0
[0.398854] RBP: 888100927c68 R08: 8881015b8f88 R09: 
[0.398855] R10:  R11:  R12: 7fff
[0.398856] R13: 777f8000 R14:  R15: 8357a758
[0.398858] FS:  () GS:888fde40()
knlGS:
[0.398859] CS:  0010 DS:  ES:  CR0: 80050033
[0.398860] CR2:  CR3: ac40c000 CR4: 00150ef0
[0.398862] Call Trace:
[0.398864]  
[0.398864]  ? iommu_setup+0x29a/0x29a
[0.398867]  ? state_next+0x6e/0x1c9
[0.398870]  ? iommu_setup+0x29a/0x29a
[0.398872]  ? iommu_go_to_state+0x1f/0x33
[0.398873]  ? amd_iommu_init+0xa/0x23
[0.398875]  ? pci_iommu_init+0xf/0x45
[0.398876]  ? iommu_setup+0x29a/0x29a
[0.398878]  ? __initstub__kmod_pci_dma__244_136_pci_iommu_initrootfs+0x5/0x8
[0.398880]  ? do_one_initcall+0x100/0x290
[0.398882]  ? do_initcall_level+0x8b/0xe5
[0.398884]  ? do_initcalls+0x44/0x6d
[0.398885]  ? kernel_init_freeable+0xc7/0x10d
[0.398886]  ? rest_init+0xc0/0xc0
[0.39]  ? kernel_init+0x11/0x150
[0.398889]  ? ret_from_fork+0x22/0x30
[0.398891]  
[0.398892] ---[ end trace f048a4ec907dc976 ]---

Which points to patch one and "if (WARN_ON(i >= LOOP_TIMEOUT))"

Hope that helps

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


Re: [PATCH v7 0/9] ACPI/IORT: Support for IORT RMR node

2022-01-25 Thread Robin Murphy

On 2022-01-25 13:00, Shameerali Kolothum Thodi wrote:

Hi Robin/Lorenzo,


-Original Message-
From: iommu [mailto:iommu-boun...@lists.linux-foundation.org] On Behalf
Of Shameer Kolothum
Sent: 05 August 2021 09:07
To: linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
iommu@lists.linux-foundation.org
Cc: robin.mur...@arm.com; j...@solid-run.com; Linuxarm
; steven.pr...@arm.com; Guohanjun (Hanjun Guo)
; yangyicong ;
sami.muja...@arm.com; w...@kernel.org; wanghuiqiang

Subject: [PATCH v7 0/9] ACPI/IORT: Support for IORT RMR node

Hi,

The series adds support to IORT RMR nodes specified in IORT
Revision E.b -ARM DEN 0049E[0]. RMR nodes are used to describe
memory ranges that are used by endpoints and require a unity
mapping in SMMU.

We have faced issues with 3408iMR RAID controller cards which
fail to boot when SMMU is enabled. This is because these
controllers make use of host memory for various caching related
purposes and when SMMU is enabled the iMR firmware fails to
access these memory regions as there is no mapping for them.
IORT RMR provides a way for UEFI to describe and report these
memory regions so that the kernel can make a unity mapping for
these in SMMU.

Change History:

v6 --> v7

The only change from v6 is the fix pointed out by Steve to
the SMMUv2 SMR bypass install in patch #8.

Thanks to the Tested-by tags by Laurentiu with SMMUv2 and
Hanjun/Huiqiang with SMMUv3 for v6. I haven't added the tags
yet as the series still needs more review[1].

Feedback and tests on this series is very much appreciated.


Since we have an update to IORT spec(E.c) now[1] and includes additional
attributes/flags for the RMR node, I am planning to respin this series soon.

Going through the new spec, I have a few queries,

The memory range attributes can now be described as one of the following,

0x00: Device-nGnRnE memory
0x01: Device-nGnRE memory
0x02: Device-nGRE memory
0x03: Device-GRE memory
0x04: Normal Inner Non-cacheable Outer Non-cacheable
0x05: Normal Inner Write-back Outer Write-back Inner Shareable

I am not sure how this needs to be captured and used in the kernel. Is there
any intention of using these fine-grained attributes in the kernel now
or a generic mapping of the above to the struct iommu_rev_region prot field
is enough? i.e., something like,

{
 
 prot = IOMMU_READ | IOMMU_WRITE;

 if (rmr_attr == normal_mem) // 0x05
 prot |= IOMMU_CACHE;
 
 if (rmr_attr == device_mem) { //0x00 - 0x03

 prot |= IOMMU_MMIO;
 prot |= IOMMU_NOEXEC;
 }
 
}


Yup, pretty much that, except don't bother with IOMMU_NOEXEC. We can't 
reliably infer it - e.g. on an AXI-based interconnect AxCACHE and AxPROT 
are entirely orthogonal, so a Device-type read with the "Instruction 
access" hint is perfectly legal - and in the common IORT code we're not 
in a position to second-guess what any given RMR might represent for 
whatever agent is accessing it.


All we can reasonably do here is map the Device types to IOMMU_MMIO and 
Write-back to IOMMU_CACHE, and if anyone ever does want to insist that 
that's not sufficient, then they're welcome to send patches to make the 
IOMMU API more expressive :)



Similarly for the 'flags' field, the new 'Access Privilege' is intended to set 
the
IOMMU_PRIV ?


Yes, exactly!

Cheers,
Robin.

   
Please let me know.


Thanks,
Shameer

[1] https://developer.arm.com/documentation/den0049/ec/?lang=en


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


Re: [PATCH 0/5] iommu/amd: fixes for suspend/resume

2022-01-25 Thread Maxim Levitsky
On Tue, 2022-01-25 at 15:08 +, Mike Lothian wrote:
> Hi
> 
> I'm seeing a WARNING that I think might be related to these patches, 
> unfortunately another issue is making bisecting difficult
> 
> [0.359362] AMD-Vi: X2APIC enabled
> [0.395140] [ cut here ]
> [0.395142] WARNING: CPU: 0 PID: 1 at 
> amd_iommu_enable_interrupts+0x1da/0x440
> [0.395146] Modules linked in:
> [0.395148] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.17.0-rc1-tip+ #2995
> [0.395150] Hardware name: ASUSTeK COMPUTER INC. ROG Strix 
> G513QY_G513QY/G513QY, BIOS G513QY.316 11/29/2021
> [0.395152] RIP: 0010:amd_iommu_enable_interrupts+0x1da/0x440
> [0.395154] Code: 4b 38 48 89 41 18 b8 a0 86 01 00 0f 1f 44 00 00 48 8b 4b 
> 38 8b 89 20 20 00 00 f7 c1 00 01 00 00 0f 85 7a fe ff ff ff c8 75 e6 <0f> 0b 
> e9 6f fe ff ff 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00
> [0.395157] RSP: 0018:88810022fc68 EFLAGS: 00010246
> [0.395158] RAX:  RBX: 88810004b000 RCX: 
> 0018
> [0.395160] RDX: 0008 RSI: 88810022fc70 RDI: 
> c90800f0
> [0.395161] RBP: 88810022fc68 R08: 888100fce088 R09: 
> 
> [0.395162] R10:  R11:  R12: 
> 7fff
> [0.395163] R13: 777f8000 R14:  R15: 
> 8357c9e8
> [0.395165] FS:  () GS:888fde40() 
> knlGS:
> [0.395166] CS:  0010 DS:  ES:  CR0: 80050033
> [0.395167] CR2: 88901e1ff000 CR3: b440c000 CR4: 
> 00150ef0
> [0.395169] Call Trace:
> [0.395170]  
> [0.395171]  ? iommu_setup+0x29a/0x29a
> [0.395174]  ? state_next+0x6e/0x1c9
> [0.395177]  ? iommu_setup+0x29a/0x29a
> [0.395178]  ? iommu_go_to_state+0x1f/0x33
> [0.395180]  ? amd_iommu_init+0xa/0x23
> [0.395182]  ? pci_iommu_init+0xf/0x45
> [0.395183]  ? iommu_setup+0x29a/0x29a
> [0.395184]  ? 
> __initstub__kmod_pci_dma__250_136_pci_iommu_initrootfs+0x5/0x8
> [0.395186]  ? do_one_initcall+0x100/0x290
> [0.395190]  ? do_initcall_level+0x8b/0xe5
> [0.395192]  ? do_initcalls+0x44/0x6d
> [0.395194]  ? kernel_init_freeable+0xc7/0x10d
> [0.395196]  ? rest_init+0xc0/0xc0
> [0.395198]  ? kernel_init+0x11/0x150
> [0.395200]  ? ret_from_fork+0x22/0x30
> [0.395201]  
> [0.395202] ---[ end trace  ]---
> [0.395204] PCI-DMA: Using software bounce buffer
> 
> Let me know if you need any more info
> 
> Cheers
> 
> Mike


Could you just apply these patches on top of 5.15 kernel and see if you get the 
warning?

If something could case it is I think patch 1, it does move the GA log enabled
to be a bit later.
I also added few warnings there. I wonder why your dmesg quote doesn't contain 
the C line
where the warning happens.

In partucular I added:

if (WARN_ON(status & (MMIO_STATUS_GALOG_RUN_MASK)))

That will fire if GA log is already running (maybe BIOS enabled it? - it really 
shouldn't do that)


And that:

if (WARN_ON(i >= LOOP_TIMEOUT))

also should not happen and worth to be logged IMHO.

Best regards,
Maxim Levitsky



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


Re: [PATCH v2] iommu/vt-d: Fix PCI bus rescan device hot add

2022-01-25 Thread Jacob Pan
Hi all,

Just wondering if there are any other comments? This fixes a
regression that can cause system hang.

On Fri, 14 Jan 2022 00:21:10 -0800, Jacob Pan
 wrote:

> During PCI bus rescan, adding new devices involve two notifiers.
> 1. dmar_pci_bus_notifier()
> 2. iommu_bus_notifier()
> The current code sets #1 as low priority (INT_MIN) which resulted in #2
> being invoked first. The result is that struct device pointer cannot be
> found in DRHD search for the new device's DMAR/IOMMU. Subsequently, the
> device is put under the "catch-all" IOMMU instead of the correct one.
> 
> This could cause system hang when device TLB invalidation is sent to the
> wrong IOMMU. Invalidation timeout error and hard lockup have been
> observed.
> 
> On the reverse direction for device removal, the order should be #2-#1
> such that DMAR cleanup is done after IOMMU.
> 
> This patch fixes the issue by setting proper priorities for
> dmar_pci_bus_notifier around IOMMU bus notifier. DRHD search for a new
> device will find the correct IOMMU. The order with this patch is the
> following:
> 1. dmar_pci_bus_add_dev()
> 2. iommu_probe_device()
> 3. iommu_release_device()
> 4. dmar_pci_bus_remove_dev()
> 
> Fixes: 59ce0515cdaf ("iommu/vt-d: Update DRHD/RMRR/ATSR device scope")
> Reported-by: Zhang, Bernice 
> Suggested-by: Lu Baolu 
> Signed-off-by: Jacob Pan 
> ---
>  drivers/iommu/intel/dmar.c | 69 --
>  drivers/iommu/iommu.c  |  1 +
>  include/linux/iommu.h  |  1 +
>  3 files changed, 53 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index 915bff76fe96..5f4751ba6bb1 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -340,15 +340,19 @@ static inline void vf_inherit_msi_domain(struct
> pci_dev *pdev) dev_set_msi_domain(>dev,
> dev_get_msi_domain(>dev)); }
>  
> -static int dmar_pci_bus_notifier(struct notifier_block *nb,
> +static int dmar_pci_bus_add_notifier(struct notifier_block *nb,
>unsigned long action, void *data)
>  {
>   struct pci_dev *pdev = to_pci_dev(data);
>   struct dmar_pci_notify_info *info;
>  
> - /* Only care about add/remove events for physical functions.
> + if (action != BUS_NOTIFY_ADD_DEVICE)
> + return NOTIFY_DONE;
> +
> + /*
>* For VFs we actually do the lookup based on the corresponding
> -  * PF in device_to_iommu() anyway. */
> +  * PF in device_to_iommu() anyway.
> +  */
>   if (pdev->is_virtfn) {
>   /*
>* Ensure that the VF device inherits the irq domain of
> the @@ -358,13 +362,34 @@ static int dmar_pci_bus_notifier(struct
> notifier_block *nb,
>* from the PF device, but that's yet another x86'sism to
>* inflict on everybody else.
>*/
> - if (action == BUS_NOTIFY_ADD_DEVICE)
> - vf_inherit_msi_domain(pdev);
> + vf_inherit_msi_domain(pdev);
>   return NOTIFY_DONE;
>   }
>  
> - if (action != BUS_NOTIFY_ADD_DEVICE &&
> - action != BUS_NOTIFY_REMOVED_DEVICE)
> + info = dmar_alloc_pci_notify_info(pdev, action);
> + if (!info)
> + return NOTIFY_DONE;
> +
> + down_write(_global_lock);
> + dmar_pci_bus_add_dev(info);
> + up_write(_global_lock);
> + dmar_free_pci_notify_info(info);
> +
> + return NOTIFY_OK;
> +}
> +
> +static struct notifier_block dmar_pci_bus_add_nb = {
> + .notifier_call = dmar_pci_bus_add_notifier,
> + .priority = IOMMU_BUS_NOTIFY_PRIORITY + 1,
> +};
> +
> +static int dmar_pci_bus_remove_notifier(struct notifier_block *nb,
> +  unsigned long action, void *data)
> +{
> + struct pci_dev *pdev = to_pci_dev(data);
> + struct dmar_pci_notify_info *info;
> +
> + if (pdev->is_virtfn || action != BUS_NOTIFY_REMOVED_DEVICE)
>   return NOTIFY_DONE;
>  
>   info = dmar_alloc_pci_notify_info(pdev, action);
> @@ -372,10 +397,7 @@ static int dmar_pci_bus_notifier(struct
> notifier_block *nb, return NOTIFY_DONE;
>  
>   down_write(_global_lock);
> - if (action == BUS_NOTIFY_ADD_DEVICE)
> - dmar_pci_bus_add_dev(info);
> - else if (action == BUS_NOTIFY_REMOVED_DEVICE)
> - dmar_pci_bus_del_dev(info);
> + dmar_pci_bus_del_dev(info);
>   up_write(_global_lock);
>  
>   dmar_free_pci_notify_info(info);
> @@ -383,11 +405,10 @@ static int dmar_pci_bus_notifier(struct
> notifier_block *nb, return NOTIFY_OK;
>  }
>  
> -static struct notifier_block dmar_pci_bus_nb = {
> - .notifier_call = dmar_pci_bus_notifier,
> - .priority = INT_MIN,
> +static struct notifier_block dmar_pci_bus_remove_nb = {
> + .notifier_call = dmar_pci_bus_remove_notifier,
> + .priority = IOMMU_BUS_NOTIFY_PRIORITY - 1,
>  };
> -
>  static struct dmar_drhd_unit *
>  dmar_find_dmaru(struct acpi_dmar_hardware_unit 

Re: [PATCH v3 0/7] MT8186 SMI SUPPORT

2022-01-25 Thread Krzysztof Kozlowski
On Thu, 13 Jan 2022 19:10:50 +0800, Yong Wu wrote:
> This patchset adds mt8186 smi support.
> mainly adds a sleep control function.
> 
> Change note:
> v3: a) Add a new binding patch for renaming "clock" to "clocks".
> b) Reword the title for the binding patches, more detailed.
> c) Add the sleep control error path: if err, return directly.
>also change the log from dev_warn to dev_err.
> 
> [...]

Applied, thanks!

[1/7] dt-bindings: memory: mtk-smi: Rename clock to clocks
  commit: 5bf7fa48374eafe29dbb30448a0b0c083853583f
[2/7] dt-bindings: memory: mtk-smi: No need mediatek,larb-id for mt8167
  commit: ddc3a324889686ec9b358de20fdeec0d2668c7a8
[3/7] dt-bindings: memory: mtk-smi: Correct minItems to 2 for the gals clocks
  commit: 996ebc0e332bfb3091395f9bd286d8349a57be62
[4/7] dt-bindings: memory: mediatek: Add mt8186 support
  commit: 6d86f23c35fe7b479ceef4d3f1eef925996945fd
[5/7] memory: mtk-smi: Fix the return value for clk_bulk_prepare_enable
  commit: a6945f4566d4f77a4054720f6649ff921fe1ae64
[6/7] memory: mtk-smi: Add sleep ctrl function
  commit: 8956500e5d5bf541a94529b0bf4866dc0daf
[7/7] memory: mtk-smi: mt8186: Add smi support
  commit: 86a010bfc73983aa8cd914f1e5f73962b0406678

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


Re: [PATCH] swiotlb: Do not zero buffer in set_memory_decrypted()

2022-01-25 Thread Tom Lendacky via iommu

On 1/25/22 07:20, Kirill A. Shutemov wrote:

For larger TDX VM, memset() after set_memory_decrypted() in
swiotlb_update_mem_attributes() takes substantial portion of boot time.

Zeroing doesn't serve any functional purpose. Malicious VMM can mess
with decrypted/shared buffer at any point.

Remove the memset().

Signed-off-by: Kirill A. Shutemov 


Acked-by: Tom Lendacky 


---
  kernel/dma/swiotlb.c | 2 --
  1 file changed, 2 deletions(-)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index f1e7ea160b43..9390b38d2897 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -207,8 +207,6 @@ void __init swiotlb_update_mem_attributes(void)
mem->vaddr = swiotlb_mem_remap(mem, bytes);
if (!mem->vaddr)
mem->vaddr = vaddr;
-
-   memset(mem->vaddr, 0, bytes);
  }
  
  static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,

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


Re: [PATCH v4 3/7] mm: page_isolation: check specified range for unmovable pages

2022-01-25 Thread Zi Yan via iommu
On 25 Jan 2022, at 8:21, Oscar Salvador wrote:

> On Tue, Jan 25, 2022 at 02:19:46PM +0100, Oscar Salvador wrote:
>> I know that this has been discussed previously, and the cover-letter already
>> mentions it, but I think it would be great to have some sort of information 
>> about
>> the problem in the commit message as well, so people do not have to go and 
>> find
>> it somewhere else.
>
> Sorry, the commit already points it out, but I meant to elaborate some more.

You got it right about the issue.

And I will add more text in the commit message and function comments to clarify
the situation.

Thanks for your suggestions.

--
Best Regards,
Yan, Zi


signature.asc
Description: OpenPGP digital signature
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH 0/5] iommu/amd: fixes for suspend/resume

2022-01-25 Thread Mike Lothian
Hi

I'm seeing a WARNING that I think might be related to these patches, 
unfortunately another issue is making bisecting difficult

[0.359362] AMD-Vi: X2APIC enabled
[0.395140] [ cut here ]
[0.395142] WARNING: CPU: 0 PID: 1 at amd_iommu_enable_interrupts+0x1da/0x440
[0.395146] Modules linked in:
[0.395148] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.17.0-rc1-tip+ #2995
[0.395150] Hardware name: ASUSTeK COMPUTER INC. ROG Strix 
G513QY_G513QY/G513QY, BIOS G513QY.316 11/29/2021
[0.395152] RIP: 0010:amd_iommu_enable_interrupts+0x1da/0x440
[0.395154] Code: 4b 38 48 89 41 18 b8 a0 86 01 00 0f 1f 44 00 00 48 8b 4b 
38 8b 89 20 20 00 00 f7 c1 00 01 00 00 0f 85 7a fe ff ff ff c8 75 e6 <0f> 0b e9 
6f fe ff ff 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00
[0.395157] RSP: 0018:88810022fc68 EFLAGS: 00010246
[0.395158] RAX:  RBX: 88810004b000 RCX: 0018
[0.395160] RDX: 0008 RSI: 88810022fc70 RDI: c90800f0
[0.395161] RBP: 88810022fc68 R08: 888100fce088 R09: 
[0.395162] R10:  R11:  R12: 7fff
[0.395163] R13: 777f8000 R14:  R15: 8357c9e8
[0.395165] FS:  () GS:888fde40() 
knlGS:
[0.395166] CS:  0010 DS:  ES:  CR0: 80050033
[0.395167] CR2: 88901e1ff000 CR3: b440c000 CR4: 00150ef0
[0.395169] Call Trace:
[0.395170]  
[0.395171]  ? iommu_setup+0x29a/0x29a
[0.395174]  ? state_next+0x6e/0x1c9
[0.395177]  ? iommu_setup+0x29a/0x29a
[0.395178]  ? iommu_go_to_state+0x1f/0x33
[0.395180]  ? amd_iommu_init+0xa/0x23
[0.395182]  ? pci_iommu_init+0xf/0x45
[0.395183]  ? iommu_setup+0x29a/0x29a
[0.395184]  ? __initstub__kmod_pci_dma__250_136_pci_iommu_initrootfs+0x5/0x8
[0.395186]  ? do_one_initcall+0x100/0x290
[0.395190]  ? do_initcall_level+0x8b/0xe5
[0.395192]  ? do_initcalls+0x44/0x6d
[0.395194]  ? kernel_init_freeable+0xc7/0x10d
[0.395196]  ? rest_init+0xc0/0xc0
[0.395198]  ? kernel_init+0x11/0x150
[0.395200]  ? ret_from_fork+0x22/0x30
[0.395201]  
[0.395202] ---[ end trace  ]---
[0.395204] PCI-DMA: Using software bounce buffer

Let me know if you need any more info

Cheers

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


Re: [PATCH v2 05/11] iommu/sva: Assign a PASID to mm on PASID allocation and free it on mm exit

2022-01-25 Thread Fenghua Yu
Hi, Thomas,

On Mon, Jan 24, 2022 at 09:55:56PM +0100, Thomas Gleixner wrote:
> On Mon, Jan 24 2022 at 12:52, Fenghua Yu wrote:
> > On Mon, Jan 24, 2022 at 09:36:00PM +0100, Thomas Gleixner wrote:
> >> On Mon, Jan 24 2022 at 21:21, Thomas Gleixner wrote:
> > Ah. This patch should remove ioasid_get(). So I will change this patch
> > as follows:
> >
> > 1. Remove ioasid_get() because it's not used any more when IOASID's
> >refcount is set to 1 once the IOASID is allocated and is freed on mm 
> > exit.
> > 2. Change mm_pasid_get() to mm_pasid_set().
> 
> Yes. Just resend this one. No need to post the full queue again.

Here is the updated patch #5. Thank you very much for your review!

>From 895f2c15385dc93acf39700014458fe275d996a2 Mon Sep 17 00:00:00 2001
From: Fenghua Yu 
Date: Thu, 18 Nov 2021 14:06:40 -0800
Subject: [PATCH v2.1 05/11] iommu/sva: Assign a PASID to mm on PASID
 allocation and free it on mm exit

To avoid complexity of updating each thread's PASID status (e.g. sending
IPI to update IA32_PASID MSR) on allocating and freeing PASID, once
allocated and assigned to an mm, the PASID stays with the mm for the
rest of the mm's lifetime. A reference to the PASID is taken on
allocating the PASID. Binding/unbinding the PASID won't change refcount.
The reference is dropped on mm exit and thus the PASID is freed.

Two helpers mm_pasid_set() and mm_pasid_drop() are defined in mm because
the PASID operations handle the pasid member in mm_struct and should be
part of mm operations. Unused ioasid_get() and iommu_sva_free_pasid()
are deleted.

20-bit PASID allows up to 1M processes bound to PASIDs at the same time.
With cgroups and other controls that might limit the number of process
creation, the limited number of PASIDs is not a realistic issue for
lazy PASID free.

Suggested-by: Dave Hansen 
Signed-off-by: Fenghua Yu 
Reviewed-by: Tony Luck 
---
v2.1:
- Rename mm_pasid_get() to mm_pasid_set() (Thomas).
- Remove ioasid_get() because it's not used any more when IOASID's
  refcount is set to 1 once the IOASID is allocated and is freed
  on mm exit (Thomas).

v2:
- Free PASID on mm exit instead of in exit(2) or unbind() (Thomas, AndyL,
  PeterZ)
- Add mm_pasid_init(), mm_pasid_get(), and mm_pasid_drop() functions in mm.
  So the mm's PASID operations are generic for both X86 and ARM
  (Dave Hansen)

 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  5 +--
 drivers/iommu/intel/svm.c |  9 -
 drivers/iommu/ioasid.c| 17 
 drivers/iommu/iommu-sva-lib.c | 39 ++-
 drivers/iommu/iommu-sva-lib.h |  1 -
 include/linux/ioasid.h|  5 ---
 include/linux/sched/mm.h  | 16 
 kernel/fork.c |  1 +
 8 files changed, 30 insertions(+), 63 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index a737ba5f727e..22ddd05bbdcd 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -340,14 +340,12 @@ __arm_smmu_sva_bind(struct device *dev, struct mm_struct 
*mm)
bond->smmu_mn = arm_smmu_mmu_notifier_get(smmu_domain, mm);
if (IS_ERR(bond->smmu_mn)) {
ret = PTR_ERR(bond->smmu_mn);
-   goto err_free_pasid;
+   goto err_free_bond;
}
 
list_add(>list, >bonds);
return >sva;
 
-err_free_pasid:
-   iommu_sva_free_pasid(mm);
 err_free_bond:
kfree(bond);
return ERR_PTR(ret);
@@ -377,7 +375,6 @@ void arm_smmu_sva_unbind(struct iommu_sva *handle)
if (refcount_dec_and_test(>refs)) {
list_del(>list);
arm_smmu_mmu_notifier_put(bond->smmu_mn);
-   iommu_sva_free_pasid(bond->mm);
kfree(bond);
}
mutex_unlock(_lock);
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 5b5d69b04fcc..51ac2096b3da 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -514,11 +514,6 @@ static int intel_svm_alloc_pasid(struct device *dev, 
struct mm_struct *mm,
return iommu_sva_alloc_pasid(mm, PASID_MIN, max_pasid - 1);
 }
 
-static void intel_svm_free_pasid(struct mm_struct *mm)
-{
-   iommu_sva_free_pasid(mm);
-}
-
 static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu,
   struct device *dev,
   struct mm_struct *mm,
@@ -662,8 +657,6 @@ static int intel_svm_unbind_mm(struct device *dev, u32 
pasid)
kfree(svm);
}
}
-   /* Drop a PASID reference and free it if no reference. */
-   intel_svm_free_pasid(mm);
}
 out:
return ret;
@@ -1047,8 +1040,6 @@ struct iommu_sva *intel_svm_bind(struct device *dev, 
struct mm_struct 

Re: [PATCH 0/7] iommu cleanup and refactoring

2022-01-25 Thread Jason Gunthorpe via iommu
On Tue, Jan 25, 2022 at 02:48:02PM +, Robin Murphy wrote:
 
> Agreed, certainly an IOMMU_DOMAIN_SVA type that can both encapsulate the mm
> and effectively replace iommu_sva seems like a logical and fairly small next
> step. We already have the paradigm of different domain types supporting
> different ops, so initially an SVA domain would simply allow bind/unbind
> rather than attach/detach/map/unmap.

I hope we can quickly get to a PASID enabled generic attach/detach
scheme - we really need this to do the uAPI part of this interface.

> they are fundamentally different things in their own right, and the ideal
> API should give us the orthogonality to also bind a device to an SVA domain
> without PASID (e.g. for KVM stage 2, or userspace assignment of simpler
> fault/stall-tolerant devices), or attach PASIDs to regular iommu_domains.

Yes, these are orthogonal things. A iommu driver that supports PASID
ideally should support PASID enabled attach/detatch for every
iommu_domain type it supports.

SVA should not be entangled with PASID beyond that SVA is often used
with PASID - a SVA iommu_domain should be fully usable with a RID too.

I'm hoping to see the core iommu code provide some simplified "SVA"
API that under the covers creates a SVA domain and then does a normal
PASID attach using the global PASID in the mm_struct - the
driver should not care what, or even if, PASID is used for a SVA
domain.

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


[PATCH] swiotlb: Do not zero buffer in set_memory_decrypted()

2022-01-25 Thread Kirill A. Shutemov
For larger TDX VM, memset() after set_memory_decrypted() in
swiotlb_update_mem_attributes() takes substantial portion of boot time.

Zeroing doesn't serve any functional purpose. Malicious VMM can mess
with decrypted/shared buffer at any point.

Remove the memset().

Signed-off-by: Kirill A. Shutemov 
---
 kernel/dma/swiotlb.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index f1e7ea160b43..9390b38d2897 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -207,8 +207,6 @@ void __init swiotlb_update_mem_attributes(void)
mem->vaddr = swiotlb_mem_remap(mem, bytes);
if (!mem->vaddr)
mem->vaddr = vaddr;
-
-   memset(mem->vaddr, 0, bytes);
 }
 
 static void swiotlb_init_io_tlb_mem(struct io_tlb_mem *mem, phys_addr_t start,
-- 
2.34.1

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


Re: [PATCH 7/7] iommu: Add iommu_domain::domain_ops

2022-01-25 Thread Jason Gunthorpe via iommu
On Tue, Jan 25, 2022 at 02:23:52PM +, Robin Murphy wrote:
> On 2022-01-25 06:27, Lu Baolu wrote:

> Where it's just about which operations are valid for which domains, it's
> even simpler for the core interface wrappers to validate the domain type,
> rather than forcing drivers to implement multiple ops structures purely for
> the sake of having different callbacks populated. We already have this in
> places, e.g. where iommu_map() checks for __IOMMU_DOMAIN_PAGING.

In my experience it is usually much clearer to directly test the op
for NULL to know if a feature is supported than to invent flags to do
the same test.  eg ops->map/etc == NULL means no paging.

I think we should not be afraid to have multiple ops in drivers for
things that are actually different in the driver. This is usually a
net win vs tying to handle all the cases with different 'if' flows.

eg identity domains and others really would ideally eventually have a
NULL ops for map/unmap too.

The 'type' should conceptually be part of the ops, not the mutable
struct - but we don't have to get there all at once.

> Paging domains are also effectively the baseline level of IOMMU API
> functionality. All drivers support them, and for the majority of drivers
> it's all they will ever support. Those drivers really don't benefit from any
> of the churn and boilerplate in this patch as-is, and it's so easy to
> compromise with a couple of lines of core code to handle the common case by
> default when the driver *isn't* one of the handful which ever actually cares
> to install their own per-domain ops. Consider how much cleaner this patch
> would look if the typical driver diff could be something completely minimal
> like this:

It is clever, but I'm not sure if hoisting a single assignment out of
the driver is worth the small long term complexity of having different
driver flows?

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


Re: [PATCH 0/7] iommu cleanup and refactoring

2022-01-25 Thread Robin Murphy

On 2022-01-24 17:44, Jason Gunthorpe wrote:

On Mon, Jan 24, 2022 at 09:46:26AM +, Tian, Kevin wrote:

From: Lu Baolu 
Sent: Monday, January 24, 2022 3:11 PM

Hi,

The guest pasid and aux-domain related code are dead code in current
iommu subtree. As we have reached a consensus that all these features
should be based on the new iommufd framework (which is under active
development), the first part of this series removes and cleanups all
the dead code.

The second part of this series refactors the iommu_domain by moving all
domain-specific ops from iommu_ops to a new domain_ops. This makes an
iommu_domain self-contained and represent the abstraction of an I/O
translation table in the IOMMU subsystem. With different type of
iommu_domain providing different set of ops, it's easier to support more
types of I/O translation tables.


You may want to give more background on this end goal. In general there
are four IOPT types in iommufd discussions:

1) The one currently tracked by iommu_domain, with a map/unmap semantics
2) The one managed by mm and shared to iommu via sva_bind/unbind ops
3) The one managed by userspace and bound to iommu via iommufd (require nesting)
4) The one managed by KVM (e.g. EPT) and shared to iommu via a TBD interface


Yes, at least from an iommufd perspective I'd like to see one struct
for all of these types, mainly so we can have a uniform alloc, attach
and detatch flow for all io page table types.


Agreed, certainly an IOMMU_DOMAIN_SVA type that can both encapsulate the 
mm and effectively replace iommu_sva seems like a logical and fairly 
small next step. We already have the paradigm of different domain types 
supporting different ops, so initially an SVA domain would simply allow 
bind/unbind rather than attach/detach/map/unmap.


It might then further be possible to hide SVA bind/unbind behind the 
attach/detach interface, but AFAICS we'd still need distinct flows for 
attaching/binding the whole device vs. attaching/binding to a PASID, 
since they are fundamentally different things in their own right, and 
the ideal API should give us the orthogonality to also bind a device to 
an SVA domain without PASID (e.g. for KVM stage 2, or userspace 
assignment of simpler fault/stall-tolerant devices), or attach PASIDs to 
regular iommu_domains.


That distinction could of course be consolidated by flipping to the 
other approach of explicitly allocating the PASID first, then wrapping 
it in a struct device that could then be passed through the same 
attach/detach interfaces and distinguished internally, but although I 
still have a fondness for that approach I know I'm about the only one :)


Cheers,
Robin.


If we want to use the iommu_domain, or make iommu_domain a sub-class
of a new struct, can be determined as we go along.

Regardless, I think this cleanup stands on its own. Moving the ops and
purging the dead code is clearly the right thing to do.

Thanks,
Jason

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


Re: [PATCH 7/7] iommu: Add iommu_domain::domain_ops

2022-01-25 Thread Robin Murphy

On 2022-01-25 06:27, Lu Baolu wrote:

On 1/25/22 8:57 AM, Robin Murphy wrote:

On 2022-01-24 07:11, Lu Baolu wrote:

Add a domain specific callback set, domain_ops, for vendor iommu driver
to provide domain specific operations. Move domain-specific callbacks
from iommu_ops to the domain_ops and hook them when a domain is 
allocated.


I think it would make a lot of sense for iommu_domain_ops to be a 
substructure *within* iommu_ops. That way we can save most of the 
driver boilerplate here by not needing extra variables everywhere, and 
letting iommu_domain_alloc() still do a default initialisation like 
"domain->ops = bus->iommu_ops->domain_ops;"


In the new model, iommu_domain_ops and iommu_ops are not 1:1 mapped.
For example, a PASID-capable IOMMU could support DMA domain (which
supports map/unmap), SVA domain (which does not), and others in the
future. Different type of domain has its own domain_ops.


Sure, it's clear that that's the direction in which this is headed, and 
as I say I'm quite excited about that. However there are a couple of 
points I think are really worth considering:


Where it's just about which operations are valid for which domains, it's 
even simpler for the core interface wrappers to validate the domain 
type, rather than forcing drivers to implement multiple ops structures 
purely for the sake of having different callbacks populated. We already 
have this in places, e.g. where iommu_map() checks for 
__IOMMU_DOMAIN_PAGING.


Paging domains are also effectively the baseline level of IOMMU API 
functionality. All drivers support them, and for the majority of drivers 
it's all they will ever support. Those drivers really don't benefit from 
any of the churn and boilerplate in this patch as-is, and it's so easy 
to compromise with a couple of lines of core code to handle the common 
case by default when the driver *isn't* one of the handful which ever 
actually cares to install their own per-domain ops. Consider how much 
cleaner this patch would look if the typical driver diff could be 
something completely minimal like this:


->8-
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index be22fcf988ce..6aff493e37ee 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -514,12 +514,14 @@ static int mtk_iommu_hw_init(const struct 
mtk_iommu_data *data)


 static const struct iommu_ops mtk_iommu_ops = {
.domain_alloc   = mtk_iommu_domain_alloc,
-   .domain_free= mtk_iommu_domain_free,
-   .attach_dev = mtk_iommu_attach_device,
-   .detach_dev = mtk_iommu_detach_device,
-   .map= mtk_iommu_map,
-   .unmap  = mtk_iommu_unmap,
-   .iova_to_phys   = mtk_iommu_iova_to_phys,
+   .domain_ops = &(const struct iommu_domain_ops){
+   .domain_free= mtk_iommu_domain_free,
+   .attach_dev = mtk_iommu_attach_device,
+   .detach_dev = mtk_iommu_detach_device,
+   .map= mtk_iommu_map,
+   .unmap  = mtk_iommu_unmap,
+   .iova_to_phys   = mtk_iommu_iova_to_phys,
+   }
.probe_device   = mtk_iommu_probe_device,
.probe_finalize = mtk_iommu_probe_finalize,
.release_device = mtk_iommu_release_device,

-8<-

And of course I have to shy away from calling it default_domain_ops, 
since although it's logically default ops for domains, it is not 
specifically ops for default domains, sigh... :)


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


Re: [PATCH v4 3/7] mm: page_isolation: check specified range for unmovable pages

2022-01-25 Thread Oscar Salvador
On Tue, Jan 25, 2022 at 02:19:46PM +0100, Oscar Salvador wrote:
> I know that this has been discussed previously, and the cover-letter already
> mentions it, but I think it would be great to have some sort of information 
> about
> the problem in the commit message as well, so people do not have to go and 
> find
> it somewhere else.

Sorry, the commit already points it out, but I meant to elaborate some more.

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


Re: [PATCH v4 3/7] mm: page_isolation: check specified range for unmovable pages

2022-01-25 Thread Oscar Salvador
On Mon, Jan 24, 2022 at 12:17:23PM -0500, Zi Yan wrote:
> You are right. Sorry for the confusion. I think it should be
> “Page isolation is done at least on max(MAX_ORDER_NR_PAEGS,
> pageblock_nr_pages) granularity.”
> 
> memory_hotplug uses PAGES_PER_SECTION. It is greater than that.

Or just specify that the max(MAX_ORDER_NR_PAGES, pageblock_nr_pages) granurality
only comes from alloc_contig_range at the moment. Other callers might want
to work in other granularity (e.g: memory-hotplug) although ultimately the
range has to be aligned to something.

> > True is that start_isolate_page_range() expects the range to be pageblock 
> > aligned and works in pageblock_nr_pages chunks, but I do not think that is 
> > what you meant to say here.
> 
> Actually, start_isolate_page_range() should expect max(MAX_ORDER_NR_PAEGS,
> pageblock_nr_pages) alignment instead of pageblock alignment. It seems to
> be an uncovered bug in the current code, since all callers uses at least
> max(MAX_ORDER_NR_PAEGS, pageblock_nr_pages) alignment.
> 
> The reason is that if start_isolate_page_range() is only pageblock aligned
> and a caller wants to isolate one pageblock from a MAX_ORDER-1
> (2 pageblocks on x84_64 systems) free page, this will lead to MIGRATE_ISOLATE
> accounting error. To avoid it, start_isolate_page_range() needs to isolate
> the max(MAX_ORDER_NR_PAEGS, pageblock_nr_pages) aligned range.

So, let me see if I get this straight:

You are saying that, currently, alloc_contig_ranges() works on the biggest
alignment otherwise we might have this scenario:

[  MAX_ORDER-1   ]
[pageblock#0][pageblock#1]

We only want to isolate pageblock#1, so we pass a pageblock-aligned range to
start_isolate_page_range(), but the page belonging to pageblock#1 spans
pageblock#0 and pageblock#1 because it is a MAX_ORDER-1 page.

So when we call set_migratetype_isolate()->set_pageblock_migratetype(), this 
will
mark either pageblock#0 or pageblock#1 as isolated, but the whole page will be 
put
in the MIGRATE_ISOLATE freelist by move_freepages_block()->move_freepages().
Meaning, we wil effectively have two pageblocks isolated, but only one marked
as such?

Did I get it right or did I miss something?

I know that this has been discussed previously, and the cover-letter already
mentions it, but I think it would be great to have some sort of information 
about
the problem in the commit message as well, so people do not have to go and find
it somewhere else.


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

Re: [PATCH 1/2] dt-bindings: mediatek: mt8186: Add binding for MM iommu

2022-01-25 Thread Krzysztof Kozlowski
On 25/01/2022 10:32, Yong Wu wrote:
> Add mt8186 iommu binding. "-mm" means the iommu is for Multimedia.
> 
> Signed-off-by: Yong Wu 
> ---
>  .../bindings/iommu/mediatek,iommu.yaml|   4 +
>  .../dt-bindings/memory/mt8186-memory-port.h   | 217 ++
>  2 files changed, 221 insertions(+)
>  create mode 100644 include/dt-bindings/memory/mt8186-memory-port.h
> 


Acked-by: Krzysztof Kozlowski 


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


RE: [PATCH v7 0/9] ACPI/IORT: Support for IORT RMR node

2022-01-25 Thread Shameerali Kolothum Thodi via iommu
Hi Robin/Lorenzo,

> -Original Message-
> From: iommu [mailto:iommu-boun...@lists.linux-foundation.org] On Behalf
> Of Shameer Kolothum
> Sent: 05 August 2021 09:07
> To: linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> iommu@lists.linux-foundation.org
> Cc: robin.mur...@arm.com; j...@solid-run.com; Linuxarm
> ; steven.pr...@arm.com; Guohanjun (Hanjun Guo)
> ; yangyicong ;
> sami.muja...@arm.com; w...@kernel.org; wanghuiqiang
> 
> Subject: [PATCH v7 0/9] ACPI/IORT: Support for IORT RMR node
> 
> Hi,
> 
> The series adds support to IORT RMR nodes specified in IORT
> Revision E.b -ARM DEN 0049E[0]. RMR nodes are used to describe
> memory ranges that are used by endpoints and require a unity
> mapping in SMMU.
> 
> We have faced issues with 3408iMR RAID controller cards which
> fail to boot when SMMU is enabled. This is because these
> controllers make use of host memory for various caching related
> purposes and when SMMU is enabled the iMR firmware fails to
> access these memory regions as there is no mapping for them.
> IORT RMR provides a way for UEFI to describe and report these
> memory regions so that the kernel can make a unity mapping for
> these in SMMU.
> 
> Change History:
> 
> v6 --> v7
> 
> The only change from v6 is the fix pointed out by Steve to
> the SMMUv2 SMR bypass install in patch #8.
> 
> Thanks to the Tested-by tags by Laurentiu with SMMUv2 and
> Hanjun/Huiqiang with SMMUv3 for v6. I haven't added the tags
> yet as the series still needs more review[1].
> 
> Feedback and tests on this series is very much appreciated.

Since we have an update to IORT spec(E.c) now[1] and includes additional
attributes/flags for the RMR node, I am planning to respin this series soon.

Going through the new spec, I have a few queries,

The memory range attributes can now be described as one of the following,

0x00: Device-nGnRnE memory
0x01: Device-nGnRE memory
0x02: Device-nGRE memory
0x03: Device-GRE memory
0x04: Normal Inner Non-cacheable Outer Non-cacheable
0x05: Normal Inner Write-back Outer Write-back Inner Shareable

I am not sure how this needs to be captured and used in the kernel. Is there
any intention of using these fine-grained attributes in the kernel now
or a generic mapping of the above to the struct iommu_rev_region prot field
is enough? i.e., something like,

{

prot = IOMMU_READ | IOMMU_WRITE;

if (rmr_attr == normal_mem) // 0x05
prot |= IOMMU_CACHE;

if (rmr_attr == device_mem) { //0x00 - 0x03
prot |= IOMMU_MMIO;
prot |= IOMMU_NOEXEC;
}

}

Similarly for the 'flags' field, the new 'Access Privilege' is intended to set 
the
IOMMU_PRIV ?
  
Please let me know.

Thanks,
Shameer

[1] https://developer.arm.com/documentation/den0049/ec/?lang=en

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


[PATCH 2/2] iommu/ipmmu-vmsa: Add support for R-Car Gen4

2022-01-25 Thread Yoshihiro Shimoda
Add support for R-Car Gen4 like r8a779f0 (R-Car S4-8). The IPMMU
hardware design of r8a779f0 is the same as r8a779a0. So, rename
"r8a779a0" to "rcar_gen4".

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/iommu/ipmmu-vmsa.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index ca752bdc710f..6c4314c2e9bf 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -719,6 +719,7 @@ static int ipmmu_init_platform_device(struct device *dev,
 
 static const struct soc_device_attribute soc_needs_opt_in[] = {
{ .family = "R-Car Gen3", },
+   { .family = "R-Car Gen4", },
{ .family = "RZ/G2", },
{ /* sentinel */ }
 };
@@ -743,7 +744,7 @@ static bool ipmmu_device_is_allowed(struct device *dev)
unsigned int i;
 
/*
-* R-Car Gen3 and RZ/G2 use the allow list to opt-in devices.
+* R-Car Gen3, Gen4 and RZ/G2 use the allow list to opt-in devices.
 * For Other SoCs, this returns true anyway.
 */
if (!soc_device_match(soc_needs_opt_in))
@@ -926,7 +927,7 @@ static const struct ipmmu_features ipmmu_features_rcar_gen3 
= {
.utlb_offset_base = 0,
 };
 
-static const struct ipmmu_features ipmmu_features_r8a779a0 = {
+static const struct ipmmu_features ipmmu_features_rcar_gen4 = {
.use_ns_alias_offset = false,
.has_cache_leaf_nodes = true,
.number_of_contexts = 16,
@@ -982,7 +983,10 @@ static const struct of_device_id ipmmu_of_ids[] = {
.data = _features_rcar_gen3,
}, {
.compatible = "renesas,ipmmu-r8a779a0",
-   .data = _features_r8a779a0,
+   .data = _features_rcar_gen4,
+   }, {
+   .compatible = "renesas,rcar-gen4-ipmmu",
+   .data = _features_rcar_gen4,
}, {
/* Terminator */
},
-- 
2.25.1

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


[PATCH 0/2] iommu/ipmmu-vmsa: Add support for R-Car Gen4

2022-01-25 Thread Yoshihiro Shimoda
This patch series is based on renesas-drivers-2022-01-11-v5.16 [1].
Note that we have to prepare the following registers' setting
in a bootloader (U-Boot) because the registers are protected.
Otherwise, data mismatch happened if dmatest with the ipmmu is running.

 => mw eed01500 0xc000; mw eed41500 0xc000

[1]
https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git/tag/?h=renesas-drivers-2022-01-11-v5.16


Yoshihiro Shimoda (2):
  dt-bindings: iommu: renesas,ipmmu-vmsa: add r8a779f0 support
  iommu/ipmmu-vmsa: Add support for R-Car Gen4

 .../devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml  |  4 
 drivers/iommu/ipmmu-vmsa.c | 10 +++---
 2 files changed, 11 insertions(+), 3 deletions(-)

-- 
2.25.1

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


[PATCH 1/2] dt-bindings: iommu: renesas, ipmmu-vmsa: add r8a779f0 support

2022-01-25 Thread Yoshihiro Shimoda
Document the compatible values for the IPMMU-VMSA blocks in
the Renesas R-Car S4-8 (R8A779F0) SoC and R-Car Gen4.

Signed-off-by: Yoshihiro Shimoda 
---
 .../devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml 
b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml
index ce0c715205c6..5159a87f3fa7 100644
--- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml
+++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml
@@ -44,6 +44,10 @@ properties:
   - renesas,ipmmu-r8a77990 # R-Car E3
   - renesas,ipmmu-r8a77995 # R-Car D3
   - renesas,ipmmu-r8a779a0 # R-Car V3U
+  - items:
+  - enum:
+  - renesas,ipmmu-r8a779f0 # R-Car S4-8
+  - const: renesas,rcar-gen4-ipmmu-vmsa  # R-Car Gen4
 
   reg:
 maxItems: 1
-- 
2.25.1

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


Re: [PATCH 7/7] iommu: Add iommu_domain::domain_ops

2022-01-25 Thread Jason Gunthorpe via iommu
On Tue, Jan 25, 2022 at 12:59:14PM +0800, Lu Baolu wrote:
> On 1/24/22 5:58 PM, Tian, Kevin wrote:
> > > From: Lu Baolu 
> > > Sent: Monday, January 24, 2022 3:11 PM
> > > +/**
> > > + * struct domain_ops - per-domain ops
> > > + * @attach_dev: attach an iommu domain to a device
> > > + * @detach_dev: detach an iommu domain from a device
> > 
> > What is the criteria about whether an op should be iommu_ops or domain_ops
> > when it requires both domain and device pointers like above two (and future
> > PASID-based attach)?
> 
> Generally ops belong to iommu_ops if they are only device oriented, and
> domain_ops if they are only domain oriented. But it's really hard to
> judge when both device and domain are involved. Good question. :-)
> 
> Perhaps we should leave the attach/detach interfaces in iommu_ops since
> they are related to device capabilities. For example, some devices
> support attach_dev_pasid, while others not.

Isn't the attach process for something like SVA or the KVM version
actually rather different code?

Ideally the function pointers should help minimize case statements/etc
inside the driver..

Or stated another way, I expect drivers will have different structs
container_of'ing back to the iommu_domain (ie intel_iommu_domain_sva,
say). Any code that needs to work differently depending on the struct
should have an op in the domain so it can sanely container_of without
a mess.

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


[PATCH 2/2] iommu/mediatek: Add mt8186 iommu support

2022-01-25 Thread Yong Wu
Add mt8186 iommu supports.

Signed-off-by: Anan Sun 
Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index be36e73e4bcc..a3124f48f9e1 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -160,6 +160,7 @@ enum mtk_iommu_plat {
M4U_MT8167,
M4U_MT8173,
M4U_MT8183,
+   M4U_MT8186,
M4U_MT8192,
M4U_MT8195,
 };
@@ -1401,6 +1402,21 @@ static const struct mtk_iommu_plat_data mt8183_data = {
.larbid_remap = {{0}, {4}, {5}, {6}, {7}, {2}, {3}, {1}},
 };
 
+static const struct mtk_iommu_plat_data mt8186_data_mm = {
+   .m4u_plat   = M4U_MT8186,
+   .flags  = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
+ WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE |
+ MTK_IOMMU_TYPE_MM,
+   .larbid_remap   = {{0}, {1, MTK_INVALID_LARBID, 8}, {4}, {7}, {2}, {9, 
11, 19, 20},
+  {MTK_INVALID_LARBID, 14, 16},
+  {MTK_INVALID_LARBID, 13, MTK_INVALID_LARBID, 17}},
+   .inv_sel_reg= REG_MMU_INV_SEL_GEN2,
+   .banks_num  = 1,
+   .banks_enable   = {true},
+   .iova_region= mt8192_multi_dom,
+   .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
+};
+
 static const struct mtk_iommu_plat_data mt8192_data = {
.m4u_plat   = M4U_MT8192,
.flags  = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
@@ -1470,6 +1486,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt8167-m4u", .data = _data},
{ .compatible = "mediatek,mt8173-m4u", .data = _data},
{ .compatible = "mediatek,mt8183-m4u", .data = _data},
+   { .compatible = "mediatek,mt8186-iommu-mm", .data = _data_mm},
{ .compatible = "mediatek,mt8192-m4u", .data = _data},
{ .compatible = "mediatek,mt8195-iommu-infra", .data = 
_data_infra},
{ .compatible = "mediatek,mt8195-iommu-vdo",   .data = 
_data_vdo},
-- 
2.18.0

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


[PATCH 1/2] dt-bindings: mediatek: mt8186: Add binding for MM iommu

2022-01-25 Thread Yong Wu
Add mt8186 iommu binding. "-mm" means the iommu is for Multimedia.

Signed-off-by: Yong Wu 
---
 .../bindings/iommu/mediatek,iommu.yaml|   4 +
 .../dt-bindings/memory/mt8186-memory-port.h   | 217 ++
 2 files changed, 221 insertions(+)
 create mode 100644 include/dt-bindings/memory/mt8186-memory-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml 
b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index c528a299afa9..6cc886eb55af 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -76,6 +76,7 @@ properties:
   - mediatek,mt8167-m4u  # generation two
   - mediatek,mt8173-m4u  # generation two
   - mediatek,mt8183-m4u  # generation two
+  - mediatek,mt8186-iommu-mm # generation two
   - mediatek,mt8192-m4u  # generation two
   - mediatek,mt8195-iommu-vdo# generation two
   - mediatek,mt8195-iommu-vpp# generation two
@@ -120,6 +121,7 @@ properties:
   dt-binding/memory/mt8167-larb-port.h for mt8167,
   dt-binding/memory/mt8173-larb-port.h for mt8173,
   dt-binding/memory/mt8183-larb-port.h for mt8183,
+  dt-binding/memory/mt8186-memory-port.h for mt8186,
   dt-binding/memory/mt8192-larb-port.h for mt8192.
   dt-binding/memory/mt8195-memory-port.h for mt8195.
 
@@ -141,6 +143,7 @@ allOf:
   - mediatek,mt2701-m4u
   - mediatek,mt2712-m4u
   - mediatek,mt8173-m4u
+  - mediatek,mt8186-iommu-mm
   - mediatek,mt8192-m4u
   - mediatek,mt8195-iommu-vdo
   - mediatek,mt8195-iommu-vpp
@@ -153,6 +156,7 @@ allOf:
   properties:
 compatible:
   enum:
+- mediatek,mt8186-iommu-mm
 - mediatek,mt8192-m4u
 - mediatek,mt8195-iommu-vdo
 - mediatek,mt8195-iommu-vpp
diff --git a/include/dt-bindings/memory/mt8186-memory-port.h 
b/include/dt-bindings/memory/mt8186-memory-port.h
new file mode 100644
index ..bda265725870
--- /dev/null
+++ b/include/dt-bindings/memory/mt8186-memory-port.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ *
+ * Author: Anan Sun 
+ * Author: Yong Wu 
+ */
+#ifndef _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_
+#define _DT_BINDINGS_MEMORY_MT8186_LARB_PORT_H_
+
+#include 
+
+/*
+ * MM IOMMU supports 16GB dma address. We separate it to four ranges:
+ * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters
+ * locate in anyone bank. BUT:
+ * a) Make sure all the ports inside a larb are in one range.
+ * b) The iova of any master can NOT cross the 4G/8G/12G boundary.
+ *
+ * This is the suggested mapping in this SoC:
+ *
+ * modulesdma-address-region   larbs-ports
+ * disp 0 ~ 4G  larb0/1/2
+ * vcodec  4G ~ 8G  larb4/7
+ * cam/mdp 8G ~ 12G the other larbs.
+ * N/A 12G ~ 16G
+ * CCU0   0x24000_ ~ 0x243ff_   larb13: port 9/10
+ * CCU1   0x24400_ ~ 0x247ff_   larb14: port 4/5
+ */
+
+/* MM IOMMU ports */
+/* LARB 0 -- MMSYS */
+#define IOMMU_PORT_L0_DISP_POSTMASK0   MTK_M4U_ID(0, 0)
+#define IOMMU_PORT_L0_REVERSED MTK_M4U_ID(0, 1)
+#define IOMMU_PORT_L0_OVL_RDMA0MTK_M4U_ID(0, 2)
+#define IOMMU_PORT_L0_DISP_FAKE0   MTK_M4U_ID(0, 3)
+
+/* LARB 1 -- MMSYS */
+#define IOMMU_PORT_L1_DISP_RDMA1   MTK_M4U_ID(1, 0)
+#define IOMMU_PORT_L1_OVL_2L_RDMA0 MTK_M4U_ID(1, 1)
+#define IOMMU_PORT_L1_DISP_RDMA0   MTK_M4U_ID(1, 2)
+#define IOMMU_PORT_L1_DISP_WDMA0   MTK_M4U_ID(1, 3)
+#define IOMMU_PORT_L1_DISP_FAKE1   MTK_M4U_ID(1, 4)
+
+/* LARB 2 -- MMSYS */
+#define IOMMU_PORT_L2_MDP_RDMA0MTK_M4U_ID(2, 0)
+#define IOMMU_PORT_L2_MDP_RDMA1MTK_M4U_ID(2, 1)
+#define IOMMU_PORT_L2_MDP_WROT0MTK_M4U_ID(2, 2)
+#define IOMMU_PORT_L2_MDP_WROT1MTK_M4U_ID(2, 3)
+#define IOMMU_PORT_L2_DISP_FAKE0   MTK_M4U_ID(2, 4)
+
+/* LARB 4 -- VDEC */
+#define IOMMU_PORT_L4_HW_VDEC_MC_EXT   MTK_M4U_ID(4, 0)
+#define IOMMU_PORT_L4_HW_VDEC_UFO_EXT  MTK_M4U_ID(4, 1)
+#define IOMMU_PORT_L4_HW_VDEC_PP_EXT   MTK_M4U_ID(4, 2)
+#define IOMMU_PORT_L4_HW_VDEC_PRED_RD_EXT  MTK_M4U_ID(4, 3)
+#define IOMMU_PORT_L4_HW_VDEC_PRED_WR_EXT  MTK_M4U_ID(4, 4)
+#define IOMMU_PORT_L4_HW_VDEC_PPWRAP_EXT   MTK_M4U_ID(4, 5)
+#define IOMMU_PORT_L4_HW_VDEC_TILE_EXT MTK_M4U_ID(4, 6)
+#define IOMMU_PORT_L4_HW_VDEC_VLD_EXT  MTK_M4U_ID(4, 7)
+#define IOMMU_PORT_L4_HW_VDEC_VLD2_EXT MTK_M4U_ID(4, 8)
+#define IOMMU_PORT_L4_HW_VDEC_AVC_MV_EXT   MTK_M4U_ID(4, 9)
+#define IOMMU_PORT_L4_HW_VDEC_UFO_ENC_EXT  MTK_M4U_ID(4, 10)
+#define IOMMU_PORT_L4_HW_VDEC_RG_CTRL_DMA_EXT  MTK_M4U_ID(4, 11)
+#define IOMMU_PORT_L4_HW_MINI_MDP_R0_EXT   MTK_M4U_ID(4, 

[PATCH 0/2] MT8186 IOMMU SUPPORT

2022-01-25 Thread Yong Wu
This patchset adds mt8186 iommu support.

Base on v5.16-rc1 and mt8195 iommu v4[1].

[1] 
https://lore.kernel.org/linux-mediatek/20220125085634.17972-1-yong...@mediatek.com/

Yong Wu (2):
  dt-bindings: mediatek: mt8186: Add binding for MM iommu
  iommu/mediatek: Add mt8186 iommu support

 .../bindings/iommu/mediatek,iommu.yaml|   4 +
 drivers/iommu/mtk_iommu.c |  17 ++
 .../dt-bindings/memory/mt8186-memory-port.h   | 217 ++
 3 files changed, 238 insertions(+)
 create mode 100644 include/dt-bindings/memory/mt8186-memory-port.h

-- 
2.18.0


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


[PATCH v4 35/35] iommu/mediatek: mt8195: Enable multi banks for infra iommu

2022-01-25 Thread Yong Wu
Enable the multi-bank functions for infra-iommu. We put PCIE in bank0
and USB in the last bank(bank4). and we don't use the other banks
currently, disable them.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index a17610434868..be36e73e4bcc 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1421,8 +1421,11 @@ static const struct mtk_iommu_plat_data 
mt8195_data_infra = {
MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT,
.pericfg_comp_str = "mediatek,mt8195-pericfg_ao",
.inv_sel_reg  = REG_MMU_INV_SEL_GEN2,
-   .banks_num= 1,
-   .banks_enable = {true},
+   .banks_num= 5,
+   .banks_enable = {true, false, false, false, true},
+   .banks_portmsk= {[0] = GENMASK(19, 16), /* PCIe */
+[4] = GENMASK(31, 20), /* USB */
+   },
.iova_region  = single_domain,
.iova_region_nr   = ARRAY_SIZE(single_domain),
 };
-- 
2.18.0

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


[PATCH v4 34/35] iommu/mediatek: Backup/restore regsiters for multi banks

2022-01-25 Thread Yong Wu
Each bank has some independent registers. thus backup/restore them for
each a bank when suspend and resume.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 46 ++-
 1 file changed, 31 insertions(+), 15 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 3a2907c19bd8..a17610434868 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -173,11 +173,12 @@ struct mtk_iommu_suspend_reg {
u32 misc_ctrl;
u32 dcm_dis;
u32 ctrl_reg;
-   u32 int_control0;
-   u32 int_main_control;
-   u32 ivrp_paddr;
u32 vld_pa_rng;
u32 wr_len_ctrl;
+
+   u32 int_control[MTK_IOMMU_BANK_MAX];
+   u32 int_main_control[MTK_IOMMU_BANK_MAX];
+   u32 ivrp_paddr[MTK_IOMMU_BANK_MAX];
 };
 
 struct mtk_iommu_plat_data {
@@ -1264,16 +1265,23 @@ static int __maybe_unused 
mtk_iommu_runtime_suspend(struct device *dev)
 {
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = >reg;
-   void __iomem *base = data->bank[0].base;
+   void __iomem *base;
+   int i = 0;
 
+   base = data->bank[i].base;
reg->wr_len_ctrl = readl_relaxed(base + REG_MMU_WR_LEN_CTRL);
reg->misc_ctrl = readl_relaxed(base + REG_MMU_MISC_CTRL);
reg->dcm_dis = readl_relaxed(base + REG_MMU_DCM_DIS);
reg->ctrl_reg = readl_relaxed(base + REG_MMU_CTRL_REG);
-   reg->int_control0 = readl_relaxed(base + REG_MMU_INT_CONTROL0);
-   reg->int_main_control = readl_relaxed(base + REG_MMU_INT_MAIN_CONTROL);
-   reg->ivrp_paddr = readl_relaxed(base + REG_MMU_IVRP_PADDR);
reg->vld_pa_rng = readl_relaxed(base + REG_MMU_VLD_PA_RNG);
+   do {
+   if (!data->plat_data->banks_enable[i])
+   continue;
+   base = data->bank[i].base;
+   reg->int_control[i] = readl_relaxed(base + 
REG_MMU_INT_CONTROL0);
+   reg->int_main_control[i] = readl_relaxed(base + 
REG_MMU_INT_MAIN_CONTROL);
+   reg->ivrp_paddr[i] = readl_relaxed(base + REG_MMU_IVRP_PADDR);
+   } while (++i < data->plat_data->banks_num);
clk_disable_unprepare(data->bclk);
return 0;
 }
@@ -1282,9 +1290,9 @@ static int __maybe_unused mtk_iommu_runtime_resume(struct 
device *dev)
 {
struct mtk_iommu_data *data = dev_get_drvdata(dev);
struct mtk_iommu_suspend_reg *reg = >reg;
-   struct mtk_iommu_domain *m4u_dom = data->bank[0].m4u_dom;
-   void __iomem *base = data->bank[0].base;
-   int ret;
+   struct mtk_iommu_domain *m4u_dom;
+   void __iomem *base;
+   int ret, i = 0;
 
ret = clk_prepare_enable(data->bclk);
if (ret) {
@@ -1296,18 +1304,26 @@ static int __maybe_unused 
mtk_iommu_runtime_resume(struct device *dev)
 * Uppon first resume, only enable the clk and return, since the values 
of the
 * registers are not yet set.
 */
-   if (!m4u_dom)
+   if (!reg->wr_len_ctrl)
return 0;
 
+   base = data->bank[i].base;
writel_relaxed(reg->wr_len_ctrl, base + REG_MMU_WR_LEN_CTRL);
writel_relaxed(reg->misc_ctrl, base + REG_MMU_MISC_CTRL);
writel_relaxed(reg->dcm_dis, base + REG_MMU_DCM_DIS);
writel_relaxed(reg->ctrl_reg, base + REG_MMU_CTRL_REG);
-   writel_relaxed(reg->int_control0, base + REG_MMU_INT_CONTROL0);
-   writel_relaxed(reg->int_main_control, base + REG_MMU_INT_MAIN_CONTROL);
-   writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
-   writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK, base + 
REG_MMU_PT_BASE_ADDR);
+   do {
+   m4u_dom = data->bank[i].m4u_dom;
+   if (!data->plat_data->banks_enable[i] || !m4u_dom)
+   continue;
+   base = data->bank[i].base;
+   writel_relaxed(reg->int_control[i], base + 
REG_MMU_INT_CONTROL0);
+   writel_relaxed(reg->int_main_control[i], base + 
REG_MMU_INT_MAIN_CONTROL);
+   writel_relaxed(reg->ivrp_paddr[i], base + REG_MMU_IVRP_PADDR);
+   writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
+  base + REG_MMU_PT_BASE_ADDR);
+   } while (++i < data->plat_data->banks_num);
 
/*
 * Users may allocate dma buffer before they call pm_runtime_get,
-- 
2.18.0

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


[PATCH v4 33/35] iommu/mediatek: Initialise/Remove for multi bank dev

2022-01-25 Thread Yong Wu
The registers for each bank of the IOMMU base are in order, delta is
0x1000. Initialise the base for each bank.

For all the previous SoC, we only have bank0. thus use "do {} while()"
to allow bank0 always go.

When removing the device, Not always all the banks are initialised, it
depend on if there is masters for that bank.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 44 ++-
 1 file changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index c6de9304bbc6..3a2907c19bd8 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -113,6 +113,7 @@
 #define F_MMU_INT_ID_PORT_ID(a)(((a) >> 2) & 0x1f)
 
 #define MTK_PROTECT_PA_ALIGN   256
+#define MTK_IOMMU_BANK_SZ  0x1000
 
 #define PERICFG_IOMMU_10x714
 
@@ -1076,7 +1077,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
struct component_match  *match = NULL;
struct regmap   *infracfg;
void*protect;
-   int ret, banks_num;
+   int ret, banks_num, i = 0;
u32 val;
char*p;
struct mtk_iommu_bank_data *bank;
@@ -1117,27 +1118,36 @@ static int mtk_iommu_probe(struct platform_device *pdev)
data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN);
}
 
+   banks_num = data->plat_data->banks_num;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   if (resource_size(res) < banks_num * MTK_IOMMU_BANK_SZ) {
+   dev_err(dev, "banknr %d. res %pR is not enough.\n", banks_num, 
res);
+   return -EINVAL;
+   }
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
ioaddr = res->start;
 
-   banks_num = data->plat_data->banks_num;
data->bank = devm_kmalloc(dev, banks_num * sizeof(*data->bank), 
GFP_KERNEL);
if (!data->bank)
return -ENOMEM;
 
-   bank = >bank[0];
-   bank->id = 0;
-   bank->base = base;
-   bank->m4u_dom = NULL;
-   bank->irq = platform_get_irq(pdev, 0);
-   if (bank->irq < 0)
-   return bank->irq;
-   bank->parent_dev = dev;
-   bank->parent_data = data;
-   spin_lock_init(>tlb_lock);
+   do {
+   if (!data->plat_data->banks_enable[i])
+   continue;
+   bank = >bank[i];
+   bank->id = i;
+   bank->base = base + i * MTK_IOMMU_BANK_SZ;
+   bank->m4u_dom = NULL;
+
+   bank->irq = platform_get_irq(pdev, i);
+   if (bank->irq < 0)
+   return bank->irq;
+   bank->parent_dev = dev;
+   bank->parent_data = data;
+   spin_lock_init(>tlb_lock);
+   } while (++i < banks_num);
 
if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_BCLK)) {
data->bclk = devm_clk_get(dev, "bclk");
@@ -1223,7 +1233,8 @@ static int mtk_iommu_probe(struct platform_device *pdev)
 static int mtk_iommu_remove(struct platform_device *pdev)
 {
struct mtk_iommu_data *data = platform_get_drvdata(pdev);
-   struct mtk_iommu_bank_data *bank = >bank[0];
+   struct mtk_iommu_bank_data *bank;
+   int i;
 
iommu_device_sysfs_remove(>iommu);
iommu_device_unregister(>iommu);
@@ -1240,7 +1251,12 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 #endif
}
pm_runtime_disable(>dev);
-   devm_free_irq(>dev, bank->irq, bank);
+   for (i = 0; i < data->plat_data->banks_num; i++) {
+   bank = >bank[i];
+   if (!bank->m4u_dom)
+   continue;
+   devm_free_irq(>dev, bank->irq, bank);
+   }
return 0;
 }
 
-- 
2.18.0

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


[PATCH v4 32/35] iommu/mediatek: Get the proper bankid for multi banks

2022-01-25 Thread Yong Wu
We preassign some ports in a special bank via the new defined
banks_portmsk. Put it in the plat_data means it is not expected to be
adjusted dynamically.

If the iommu id in the iommu consumer's dtsi node is inside this
banks_portmsk, then we switch it to this special iommu bank, and
initialise the IOMMU bank HW.

Each a bank has the independent pgtable(4GB iova range). Each a bank
is a independent iommu domain/group. Currently we don't separate different
iova ranges inside a bank.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 39 ---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 22586d1aed72..c6de9304bbc6 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -191,6 +191,7 @@ struct mtk_iommu_plat_data {
 
u8  banks_num;
boolbanks_enable[MTK_IOMMU_BANK_MAX];
+   unsigned intbanks_portmsk[MTK_IOMMU_BANK_MAX];
unsigned char   larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX];
 };
 
@@ -478,6 +479,30 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static unsigned int mtk_iommu_get_bank_id(struct device *dev,
+ const struct mtk_iommu_plat_data 
*plat_data)
+{
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+   unsigned int i, portmsk = 0, bankid = 0;
+
+   if (plat_data->banks_num == 1)
+   return bankid;
+
+   for (i = 0; i < fwspec->num_ids; i++)
+   portmsk |= BIT(MTK_M4U_TO_PORT(fwspec->ids[i]));
+
+   for (i = 0; i < plat_data->banks_num && i < MTK_IOMMU_BANK_MAX; i++) {
+   if (!plat_data->banks_enable[i])
+   continue;
+
+   if (portmsk & plat_data->banks_portmsk[i]) {
+   bankid = i;
+   break;
+   }
+   }
+   return bankid; /* default is 0 */
+}
+
 static int mtk_iommu_get_iova_region_id(struct device *dev,
const struct mtk_iommu_plat_data 
*plat_data)
 {
@@ -630,13 +655,14 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
struct list_head *hw_list = data->hw_list;
struct device *m4udev = data->dev;
struct mtk_iommu_bank_data *bank;
-   unsigned int bankid = 0;
+   unsigned int bankid;
int ret, region_id;
 
region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data);
if (region_id < 0)
return region_id;
 
+   bankid = mtk_iommu_get_bank_id(dev, data->plat_data);
mutex_lock(>mutex);
if (!dom->bank) {
/* Data is in the frstdata in sharing pgtable case. */
@@ -778,6 +804,7 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data;
struct list_head *hw_list = c_data->hw_list;
struct iommu_group *group;
+   unsigned int bankid, groupid;
int regionid;
 
data = mtk_iommu_get_frst_data(hw_list);
@@ -788,12 +815,18 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
if (regionid < 0)
return ERR_PTR(regionid);
 
+   bankid = mtk_iommu_get_bank_id(dev, data->plat_data);
mutex_lock(>mutex);
-   group = data->m4u_group[regionid];
+   /*
+* If the bank function is enabled, each a bank is a iommu group/domain.
+* otherwise, each a iova region is a iommu group/domain.
+*/
+   groupid = bankid ? bankid : regionid;
+   group = data->m4u_group[groupid];
if (!group) {
group = iommu_group_alloc();
if (!IS_ERR(group))
-   data->m4u_group[regionid] = group;
+   data->m4u_group[groupid] = group;
} else {
iommu_group_ref_get(group);
}
-- 
2.18.0

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


[PATCH v4 31/35] iommu/mediatek: Change the domid to iova_region_id

2022-01-25 Thread Yong Wu
Prepare for adding bankid, also no functional change.

In the previous SoC, each a iova_region is a domain; In the multi-banks
case, each a bank is a domain, then the original function name
"mtk_iommu_get_domain_id" is not proper. Use "iova_region_id" instead of
"domain_id".

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 46 +++
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index c0843c67b5a7..22586d1aed72 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -478,8 +478,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
-static int mtk_iommu_get_domain_id(struct device *dev,
-  const struct mtk_iommu_plat_data *plat_data)
+static int mtk_iommu_get_iova_region_id(struct device *dev,
+   const struct mtk_iommu_plat_data 
*plat_data)
 {
const struct mtk_iommu_iova_region *rgn = plat_data->iova_region;
const struct bus_dma_region *dma_rgn = dev->dma_range_map;
@@ -509,7 +509,7 @@ static int mtk_iommu_get_domain_id(struct device *dev,
 }
 
 static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
-   bool enable, unsigned int domid)
+   bool enable, unsigned int regionid)
 {
struct mtk_smi_larb_iommu*larb_mmu;
unsigned int larbid, portid;
@@ -525,12 +525,12 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, 
struct device *dev,
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
larb_mmu = >larb_imu[larbid];
 
-   region = data->plat_data->iova_region + domid;
+   region = data->plat_data->iova_region + regionid;
larb_mmu->bank[portid] = 
upper_32_bits(region->iova_base);
 
-   dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank 
%d.\n",
+   dev_dbg(dev, "%s iommu for larb(%s) port %d region %d 
rgn-bank %d.\n",
enable ? "enable" : "disable", 
dev_name(larb_mmu->dev),
-   portid, domid, larb_mmu->bank[portid]);
+   portid, regionid, larb_mmu->bank[portid]);
 
if (enable)
larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
@@ -556,7 +556,7 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, 
struct device *dev,
 
 static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
 struct mtk_iommu_data *data,
-unsigned int domid)
+unsigned int region_id)
 {
const struct mtk_iommu_iova_region *region;
struct mtk_iommu_domain *m4u_dom;
@@ -595,7 +595,7 @@ static int mtk_iommu_domain_finalise(struct 
mtk_iommu_domain *dom,
 
 update_iova_region:
/* Update the iova region for this domain */
-   region = data->plat_data->iova_region + domid;
+   region = data->plat_data->iova_region + region_id;
dom->domain.geometry.aperture_start = region->iova_base;
dom->domain.geometry.aperture_end = region->iova_base + region->size - 
1;
dom->domain.geometry.force_aperture = true;
@@ -631,18 +631,18 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
struct device *m4udev = data->dev;
struct mtk_iommu_bank_data *bank;
unsigned int bankid = 0;
-   int ret, domid;
+   int ret, region_id;
 
-   domid = mtk_iommu_get_domain_id(dev, data->plat_data);
-   if (domid < 0)
-   return domid;
+   region_id = mtk_iommu_get_iova_region_id(dev, data->plat_data);
+   if (region_id < 0)
+   return region_id;
 
mutex_lock(>mutex);
if (!dom->bank) {
/* Data is in the frstdata in sharing pgtable case. */
frstdata = mtk_iommu_get_frst_data(hw_list);
 
-   ret = mtk_iommu_domain_finalise(dom, frstdata, domid);
+   ret = mtk_iommu_domain_finalise(dom, frstdata, region_id);
if (ret) {
mutex_unlock(>mutex);
return -ENODEV;
@@ -673,7 +673,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
}
mutex_unlock(>mutex);
 
-   return mtk_iommu_config(data, dev, true, domid);
+   return mtk_iommu_config(data, dev, true, region_id);
 
 data_unlock:
mutex_unlock(>mutex);
@@ -778,22 +778,22 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data;
struct list_head *hw_list = c_data->hw_list;
struct iommu_group *group;
-   

[PATCH v4 30/35] iommu/mediatek: Initialise bank HW for each a bank

2022-01-25 Thread Yong Wu
The mt8195 IOMMU HW max support 5 banks, and regarding the banks'
registers, it looks like:

 
 |bank0  | bank1 | bank2 | bank3 | bank4|
 
 |global |
 |control| null
 |regs   |
 -
 |bank   |bank   |bank   |bank   |bank   |
 |regs   |regs   |regs   |regs   |regs   |
 |   |   |   |   |   |
 -

Each bank has some special bank registers and it share bank0's global
control registers. this patch initialise the bank hw with the bankid.

In the hw_init, we always initialise bank0's control register since
we don't know if the bank0 is initialised.

Additionally, About each bank's register base, always delta 0x1000.
like bank[x + 1] = bank[x] + 0x1000.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 32 
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index dc47dc0e3163..c0843c67b5a7 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -270,7 +270,7 @@ static inline void mtk_iommu_unbind(struct device *dev)
 
 static const struct iommu_ops mtk_iommu_ops;
 
-static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int 
bankid);
 
 #define MTK_IOMMU_TLB_ADDR(iova) ({\
dma_addr_t _addr = iova;\
@@ -653,12 +653,14 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
 
mutex_lock(>mutex);
bank = >bank[bankid];
-   if (!bank->m4u_dom) { /* Initialize the M4U HW */
+   if (!bank->m4u_dom) { /* Initialize the M4U HW for each a BANK */
ret = pm_runtime_resume_and_get(m4udev);
-   if (ret < 0)
+   if (ret < 0) {
+   dev_err(m4udev, "pm get fail(%d) in attach.\n", ret);
goto data_unlock;
+   }
 
-   ret = mtk_iommu_hw_init(data);
+   ret = mtk_iommu_hw_init(data, bankid);
if (ret) {
pm_runtime_put(m4udev);
goto data_unlock;
@@ -871,11 +873,16 @@ static const struct iommu_ops mtk_iommu_ops = {
.owner  = THIS_MODULE,
 };
 
-static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)
+static int mtk_iommu_hw_init(const struct mtk_iommu_data *data, unsigned int 
bankid)
 {
+   const struct mtk_iommu_bank_data *bankx = >bank[bankid];
const struct mtk_iommu_bank_data *bank0 = >bank[0];
u32 regval;
 
+   /*
+* Global control settings are in bank0. May re-init these global 
registers
+* since no sure if there is bank0 consumers.
+*/
if (data->plat_data->m4u_plat == M4U_MT8173) {
regval = F_MMU_PREFETCH_RT_REPLACE_MOD |
 F_MMU_TF_PROT_TO_PROGRAM_ADDR_MT8173;
@@ -918,13 +925,14 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
}
writel_relaxed(regval, bank0->base + REG_MMU_MISC_CTRL);
 
+   /* Independent settings for each bank */
regval = F_L2_MULIT_HIT_EN |
F_TABLE_WALK_FAULT_INT_EN |
F_PREETCH_FIFO_OVERFLOW_INT_EN |
F_MISS_FIFO_OVERFLOW_INT_EN |
F_PREFETCH_FIFO_ERR_INT_EN |
F_MISS_FIFO_ERR_INT_EN;
-   writel_relaxed(regval, bank0->base + REG_MMU_INT_CONTROL0);
+   writel_relaxed(regval, bankx->base + REG_MMU_INT_CONTROL0);
 
regval = F_INT_TRANSLATION_FAULT |
F_INT_MAIN_MULTI_HIT_FAULT |
@@ -933,19 +941,19 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
F_INT_TLB_MISS_FAULT |
F_INT_MISS_TRANSACTION_FIFO_FAULT |
F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
-   writel_relaxed(regval, bank0->base + REG_MMU_INT_MAIN_CONTROL);
+   writel_relaxed(regval, bankx->base + REG_MMU_INT_MAIN_CONTROL);
 
if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
else
regval = lower_32_bits(data->protect_base) |
 upper_32_bits(data->protect_base);
-   writel_relaxed(regval, bank0->base + REG_MMU_IVRP_PADDR);
+   writel_relaxed(regval, bankx->base + REG_MMU_IVRP_PADDR);
 
-   if (devm_request_irq(bank0->parent_dev, bank0->irq, mtk_iommu_isr, 0,
-dev_name(bank0->parent_dev), (void *)bank0)) {
-   writel_relaxed(0, bank0->base + REG_MMU_PT_BASE_ADDR);
-   dev_err(bank0->parent_dev, "Failed @ IRQ-%d Request\n", 
bank0->irq);
+   if (devm_request_irq(bankx->parent_dev, 

[PATCH v4 29/35] iommu/mediatek: Add mtk_iommu_bank_data structure

2022-01-25 Thread Yong Wu
Prepare for supporting multi-banks for the IOMMU HW, No functional change.

Add a new structure(mtk_iommu_bank_data) for each a bank. Each a bank have
the independent HW base/IRQ/tlb-range ops, and each a bank has its special
iommu-domain(independent pgtable), thus, also move the domain information
into it.

In previous SoC, we have only one bank which could be treated as bank0(
bankid always is 0 for the previous SoC).

After adding this structure, the tlb operations and irq could use
bank_data as parameter.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 179 +-
 1 file changed, 117 insertions(+), 62 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index f88c7bb235bf..dc47dc0e3163 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -151,6 +151,7 @@
 #define MTK_LARB_SUBCOM_MAX8
 
 #define MTK_IOMMU_GROUP_MAX8
+#define MTK_IOMMU_BANK_MAX 5
 
 enum mtk_iommu_plat {
M4U_MT2712,
@@ -187,25 +188,36 @@ struct mtk_iommu_plat_data {
struct list_head*hw_list;
unsigned intiova_region_nr;
const struct mtk_iommu_iova_region  *iova_region;
+
+   u8  banks_num;
+   boolbanks_enable[MTK_IOMMU_BANK_MAX];
unsigned char   larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX];
 };
 
-struct mtk_iommu_data {
+struct mtk_iommu_bank_data {
void __iomem*base;
int irq;
+   u8  id;
+   struct device   *parent_dev;
+   struct mtk_iommu_data   *parent_data;
+   spinlock_t  tlb_lock; /* lock for tlb range flush */
+   struct mtk_iommu_domain *m4u_dom; /* Each bank has a domain */
+};
+
+struct mtk_iommu_data {
struct device   *dev;
struct clk  *bclk;
phys_addr_t protect_base; /* protect memory base */
struct mtk_iommu_suspend_regreg;
-   struct mtk_iommu_domain *m4u_dom;
struct iommu_group  *m4u_group[MTK_IOMMU_GROUP_MAX];
boolenable_4GB;
-   spinlock_t  tlb_lock; /* lock for tlb range flush */
 
struct iommu_device iommu;
const struct mtk_iommu_plat_data *plat_data;
struct device   *smicomm_dev;
 
+   struct mtk_iommu_bank_data  *bank;
+
struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */
struct regmap   *pericfg;
 
@@ -225,7 +237,7 @@ struct mtk_iommu_domain {
struct io_pgtable_cfg   cfg;
struct io_pgtable_ops   *iop;
 
-   struct mtk_iommu_data   *data;
+   struct mtk_iommu_bank_data  *bank;
struct iommu_domain domain;
 
struct mutexmutex; /* Protect "data" in this 
structure */
@@ -322,20 +334,24 @@ static struct mtk_iommu_domain *to_mtk_domain(struct 
iommu_domain *dom)
 
 static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
 {
-   void __iomem *base = data->base;
+   /* Tlb flush all always is in bank0. */
+   struct mtk_iommu_bank_data *bank = >bank[0];
+   void __iomem *base = bank->base;
unsigned long flags;
 
-   spin_lock_irqsave(>tlb_lock, flags);
+   spin_lock_irqsave(>tlb_lock, flags);
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + 
data->plat_data->inv_sel_reg);
writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE);
wmb(); /* Make sure the tlb flush all done */
-   spin_unlock_irqrestore(>tlb_lock, flags);
+   spin_unlock_irqrestore(>tlb_lock, flags);
 }
 
 static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
-  struct mtk_iommu_data *data)
+  struct mtk_iommu_bank_data *bank)
 {
-   struct list_head *head = data->hw_list;
+   struct list_head *head = bank->parent_data->hw_list;
+   struct mtk_iommu_bank_data *curbank;
+   struct mtk_iommu_data *data;
bool check_pm_status;
unsigned long flags;
void __iomem *base;
@@ -365,9 +381,10 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t size,
continue;
}
 
-   base = data->base;
+   curbank = >bank[bank->id];
+   base = curbank->base;
 
-   spin_lock_irqsave(>tlb_lock, flags);
+   spin_lock_irqsave(>tlb_lock, flags);
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
   base + data->plat_data->inv_sel_reg);
 
@@ -382,7 +399,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t 

[PATCH v4 28/35] iommu/mediatek-v1: Just rename mtk_iommu to mtk_iommu_v1

2022-01-25 Thread Yong Wu
No functional change. Just rename this for readable.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu_v1.c | 209 +--
 1 file changed, 102 insertions(+), 107 deletions(-)

diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 23c3bc175153..72d5cbeeaecf 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -85,34 +85,34 @@
  */
 #define M2701_IOMMU_PGT_SIZE   SZ_4M
 
-struct mtk_iommu_suspend_reg {
+struct mtk_iommu_v1_suspend_reg {
u32 standard_axi_mode;
u32 dcm_dis;
u32 ctrl_reg;
u32 int_control0;
 };
 
-struct mtk_iommu_data {
+struct mtk_iommu_v1_data {
void __iomem*base;
int irq;
struct device   *dev;
struct clk  *bclk;
phys_addr_t protect_base; /* protect memory base */
-   struct mtk_iommu_domain *m4u_dom;
+   struct mtk_iommu_v1_domain  *m4u_dom;
 
struct iommu_device iommu;
struct dma_iommu_mapping*mapping;
struct mtk_smi_larb_iommu   larb_imu[MTK_LARB_NR_MAX];
 
-   struct mtk_iommu_suspend_regreg;
+   struct mtk_iommu_v1_suspend_reg reg;
 };
 
-struct mtk_iommu_domain {
+struct mtk_iommu_v1_domain {
spinlock_t  pgtlock; /* lock for page table */
struct iommu_domain domain;
u32 *pgt_va;
dma_addr_t  pgt_pa;
-   struct mtk_iommu_data   *data;
+   struct mtk_iommu_v1_data*data;
 };
 
 static inline int compare_of(struct device *dev, void *data)
@@ -125,23 +125,23 @@ static inline void release_of(struct device *dev, void 
*data)
of_node_put(data);
 }
 
-static inline int mtk_iommu_bind(struct device *dev)
+static inline int mtk_iommu_v1_bind(struct device *dev)
 {
-   struct mtk_iommu_data *data = dev_get_drvdata(dev);
+   struct mtk_iommu_v1_data *data = dev_get_drvdata(dev);
 
return component_bind_all(dev, >larb_imu);
 }
 
-static inline void mtk_iommu_unbind(struct device *dev)
+static inline void mtk_iommu_v1_unbind(struct device *dev)
 {
-   struct mtk_iommu_data *data = dev_get_drvdata(dev);
+   struct mtk_iommu_v1_data *data = dev_get_drvdata(dev);
 
component_unbind_all(dev, >larb_imu);
 }
 
-static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
+static struct mtk_iommu_v1_domain *to_mtk_domain(struct iommu_domain *dom)
 {
-   return container_of(dom, struct mtk_iommu_domain, domain);
+   return container_of(dom, struct mtk_iommu_v1_domain, domain);
 }
 
 static const int mt2701_m4u_in_larb[] = {
@@ -167,7 +167,7 @@ static inline int mt2701_m4u_to_port(int id)
return id - mt2701_m4u_in_larb[larb];
 }
 
-static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
+static void mtk_iommu_v1_tlb_flush_all(struct mtk_iommu_v1_data *data)
 {
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
data->base + REG_MMU_INV_SEL);
@@ -175,8 +175,8 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data 
*data)
wmb(); /* Make sure the tlb flush all done */
 }
 
-static void mtk_iommu_tlb_flush_range(struct mtk_iommu_data *data,
-   unsigned long iova, size_t size)
+static void mtk_iommu_v1_tlb_flush_range(struct mtk_iommu_v1_data *data,
+unsigned long iova, size_t size)
 {
int ret;
u32 tmp;
@@ -194,16 +194,16 @@ static void mtk_iommu_tlb_flush_range(struct 
mtk_iommu_data *data,
if (ret) {
dev_warn(data->dev,
 "Partial TLB flush timed out, falling back to full 
flush\n");
-   mtk_iommu_tlb_flush_all(data);
+   mtk_iommu_v1_tlb_flush_all(data);
}
/* Clear the CPE status */
writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
 }
 
-static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
+static irqreturn_t mtk_iommu_v1_isr(int irq, void *dev_id)
 {
-   struct mtk_iommu_data *data = dev_id;
-   struct mtk_iommu_domain *dom = data->m4u_dom;
+   struct mtk_iommu_v1_data *data = dev_id;
+   struct mtk_iommu_v1_domain *dom = data->m4u_dom;
u32 int_state, regval, fault_iova, fault_pa;
unsigned int fault_larb, fault_port;
 
@@ -233,13 +233,13 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
regval |= F_INT_CLR_BIT;
writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL);
 
-   mtk_iommu_tlb_flush_all(data);
+   mtk_iommu_v1_tlb_flush_all(data);
 
return IRQ_HANDLED;
 }
 
-static void mtk_iommu_config(struct mtk_iommu_data *data,
-struct device *dev, bool enable)

[PATCH v4 27/35] iommu/mediatek: Remove mtk_iommu.h

2022-01-25 Thread Yong Wu
Currently there is only compare_of/release_of/a suspend structure in the
header file. I think it is no need to keep a header file only for these.
Move these into the c file and rm this header file.

I think there should be a common helper for compare_of and release_of.
There is many copy in drm, it should be another topic.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c| 25 -
 drivers/iommu/mtk_iommu.h| 42 
 drivers/iommu/mtk_iommu_v1.c | 21 +++---
 3 files changed, 42 insertions(+), 46 deletions(-)
 delete mode 100644 drivers/iommu/mtk_iommu.h

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 80c1e5a75868..f88c7bb235bf 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -30,7 +31,7 @@
 #include 
 #include 
 
-#include "mtk_iommu.h"
+#include 
 
 #define REG_MMU_PT_BASE_ADDR   0x000
 #define MMU_PT_ADDR_MASK   GENMASK(31, 7)
@@ -166,6 +167,17 @@ struct mtk_iommu_iova_region {
unsigned long long  size;
 };
 
+struct mtk_iommu_suspend_reg {
+   u32 misc_ctrl;
+   u32 dcm_dis;
+   u32 ctrl_reg;
+   u32 int_control0;
+   u32 int_main_control;
+   u32 ivrp_paddr;
+   u32 vld_pa_rng;
+   u32 wr_len_ctrl;
+};
+
 struct mtk_iommu_plat_data {
enum mtk_iommu_plat m4u_plat;
u32 flags;
@@ -219,6 +231,17 @@ struct mtk_iommu_domain {
struct mutexmutex; /* Protect "data" in this 
structure */
 };
 
+/* TODO: A common helper is expected. */
+static inline int compare_of(struct device *dev, void *data)
+{
+   return dev->of_node == data;
+}
+
+static inline void release_of(struct device *dev, void *data)
+{
+   of_node_put(data);
+}
+
 static inline int mtk_iommu_bind(struct device *dev)
 {
struct mtk_iommu_data *data = dev_get_drvdata(dev);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
deleted file mode 100644
index d332f9769f83..
--- a/drivers/iommu/mtk_iommu.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2015-2016 MediaTek Inc.
- * Author: Honghui Zhang 
- */
-
-#ifndef _MTK_IOMMU_H_
-#define _MTK_IOMMU_H_
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-struct mtk_iommu_suspend_reg {
-   union {
-   u32 standard_axi_mode;/* v1 */
-   u32 misc_ctrl;/* v2 */
-   };
-   u32 dcm_dis;
-   u32 ctrl_reg;
-   u32 int_control0;
-   u32 int_main_control;
-   u32 ivrp_paddr;
-   u32 vld_pa_rng;
-   u32 wr_len_ctrl;
-};
-
-static inline int compare_of(struct device *dev, void *data)
-{
-   return dev->of_node == data;
-}
-
-static inline void release_of(struct device *dev, void *data)
-{
-   of_node_put(data);
-}
-
-#endif
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index b762a05328d4..23c3bc175153 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -7,7 +7,6 @@
  *
  * Based on driver/iommu/mtk_iommu.c
  */
-#include 
 #include 
 #include 
 #include 
@@ -28,10 +27,9 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
-#include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR   0x000
 
@@ -87,6 +85,13 @@
  */
 #define M2701_IOMMU_PGT_SIZE   SZ_4M
 
+struct mtk_iommu_suspend_reg {
+   u32 standard_axi_mode;
+   u32 dcm_dis;
+   u32 ctrl_reg;
+   u32 int_control0;
+};
+
 struct mtk_iommu_data {
void __iomem*base;
int irq;
@@ -110,6 +115,16 @@ struct mtk_iommu_domain {
struct mtk_iommu_data   *data;
 };
 
+static inline int compare_of(struct device *dev, void *data)
+{
+   return dev->of_node == data;
+}
+
+static inline void release_of(struct device *dev, void *data)
+{
+   of_node_put(data);
+}
+
 static inline int mtk_iommu_bind(struct device *dev)
 {
struct mtk_iommu_data *data = dev_get_drvdata(dev);
-- 
2.18.0

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


[PATCH v4 26/35] iommu/mediatek: Separate mtk_iommu_data for v1 and v2

2022-01-25 Thread Yong Wu
Prepare for adding the structure "mtk_iommu_bank_data". No functional
change. The mtk_iommu_domain in v1 and v2 are different, we could not add
current data as bank[0] in v1 simplistically.

Currently we have no plan to add new SoC for v1, in order to avoid affect
v1 when we add many new features for v2, I totally separate v1 and v2 in
this patch, there are many structures only for v2.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c| 82 +---
 drivers/iommu/mtk_iommu.h| 81 ---
 drivers/iommu/mtk_iommu_v1.c | 29 +
 3 files changed, 106 insertions(+), 86 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 496ed9ecd23a..80c1e5a75868 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -146,6 +146,69 @@
 
 #define MTK_INVALID_LARBID MTK_LARB_NR_MAX
 
+#define MTK_LARB_COM_MAX   8
+#define MTK_LARB_SUBCOM_MAX8
+
+#define MTK_IOMMU_GROUP_MAX8
+
+enum mtk_iommu_plat {
+   M4U_MT2712,
+   M4U_MT6779,
+   M4U_MT8167,
+   M4U_MT8173,
+   M4U_MT8183,
+   M4U_MT8192,
+   M4U_MT8195,
+};
+
+struct mtk_iommu_iova_region {
+   dma_addr_t  iova_base;
+   unsigned long long  size;
+};
+
+struct mtk_iommu_plat_data {
+   enum mtk_iommu_plat m4u_plat;
+   u32 flags;
+   u32 inv_sel_reg;
+
+   char*pericfg_comp_str;
+   struct list_head*hw_list;
+   unsigned intiova_region_nr;
+   const struct mtk_iommu_iova_region  *iova_region;
+   unsigned char   larbid_remap[MTK_LARB_COM_MAX][MTK_LARB_SUBCOM_MAX];
+};
+
+struct mtk_iommu_data {
+   void __iomem*base;
+   int irq;
+   struct device   *dev;
+   struct clk  *bclk;
+   phys_addr_t protect_base; /* protect memory base */
+   struct mtk_iommu_suspend_regreg;
+   struct mtk_iommu_domain *m4u_dom;
+   struct iommu_group  *m4u_group[MTK_IOMMU_GROUP_MAX];
+   boolenable_4GB;
+   spinlock_t  tlb_lock; /* lock for tlb range flush */
+
+   struct iommu_device iommu;
+   const struct mtk_iommu_plat_data *plat_data;
+   struct device   *smicomm_dev;
+
+   struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */
+   struct regmap   *pericfg;
+
+   struct mutexmutex; /* Protect m4u_group/m4u_dom 
above */
+
+   /*
+* In the sharing pgtable case, list data->list to the global list like 
m4ulist.
+* In the non-sharing pgtable case, list data->list to the itself 
hw_list_head.
+*/
+   struct list_head*hw_list;
+   struct list_headhw_list_head;
+   struct list_headlist;
+   struct mtk_smi_larb_iommu   larb_imu[MTK_LARB_NR_MAX];
+};
+
 struct mtk_iommu_domain {
struct io_pgtable_cfg   cfg;
struct io_pgtable_ops   *iop;
@@ -156,6 +219,20 @@ struct mtk_iommu_domain {
struct mutexmutex; /* Protect "data" in this 
structure */
 };
 
+static inline int mtk_iommu_bind(struct device *dev)
+{
+   struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+   return component_bind_all(dev, >larb_imu);
+}
+
+static inline void mtk_iommu_unbind(struct device *dev)
+{
+   struct mtk_iommu_data *data = dev_get_drvdata(dev);
+
+   component_unbind_all(dev, >larb_imu);
+}
+
 static const struct iommu_ops mtk_iommu_ops;
 
 static int mtk_iommu_hw_init(const struct mtk_iommu_data *data);
@@ -193,11 +270,6 @@ static LIST_HEAD(m4ulist); /* List all the M4U HWs */
 
 #define for_each_m4u(data, head)  list_for_each_entry(data, head, list)
 
-struct mtk_iommu_iova_region {
-   dma_addr_t  iova_base;
-   unsigned long long  size;
-};
-
 static const struct mtk_iommu_iova_region single_domain[] = {
{.iova_base = 0,.size = SZ_4G},
 };
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 9dba98bb12eb..d332f9769f83 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -7,23 +7,14 @@
 #ifndef _MTK_IOMMU_H_
 #define _MTK_IOMMU_H_
 
-#include 
-#include 
 #include 
 #include 
 #include 
 #include 
-#include 
 #include 
-#include 
 #include 
 #include 
 
-#define MTK_LARB_COM_MAX   8
-#define MTK_LARB_SUBCOM_MAX8
-
-#define MTK_IOMMU_GROUP_MAX8
-
 struct mtk_iommu_suspend_reg {
union {
u32 standard_axi_mode;/* v1 */
@@ -38,64 +29,6 @@ struct mtk_iommu_suspend_reg {

[PATCH v4 25/35] iommu/mediatek: Just move code position in hw_init

2022-01-25 Thread Yong Wu
No functional change too, prepare for mt8195 IOMMU support bank functions.
Some global control settings are in bank0 while the other banks have
their bank independent setting. Here only move the global control
settings and the independent registers together.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 48 +++
 1 file changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index fdc14db5b4c0..496ed9ecd23a 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -766,30 +766,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
}
writel_relaxed(regval, data->base + REG_MMU_CTRL_REG);
 
-   regval = F_L2_MULIT_HIT_EN |
-   F_TABLE_WALK_FAULT_INT_EN |
-   F_PREETCH_FIFO_OVERFLOW_INT_EN |
-   F_MISS_FIFO_OVERFLOW_INT_EN |
-   F_PREFETCH_FIFO_ERR_INT_EN |
-   F_MISS_FIFO_ERR_INT_EN;
-   writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
-
-   regval = F_INT_TRANSLATION_FAULT |
-   F_INT_MAIN_MULTI_HIT_FAULT |
-   F_INT_INVALID_PA_FAULT |
-   F_INT_ENTRY_REPLACEMENT_FAULT |
-   F_INT_TLB_MISS_FAULT |
-   F_INT_MISS_TRANSACTION_FIFO_FAULT |
-   F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
-   writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
-
-   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
-   regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
-   else
-   regval = lower_32_bits(data->protect_base) |
-upper_32_bits(data->protect_base);
-   writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
-
if (data->enable_4GB &&
MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_VLD_PA_RNG)) {
/*
@@ -823,6 +799,30 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
}
writel_relaxed(regval, data->base + REG_MMU_MISC_CTRL);
 
+   regval = F_L2_MULIT_HIT_EN |
+   F_TABLE_WALK_FAULT_INT_EN |
+   F_PREETCH_FIFO_OVERFLOW_INT_EN |
+   F_MISS_FIFO_OVERFLOW_INT_EN |
+   F_PREFETCH_FIFO_ERR_INT_EN |
+   F_MISS_FIFO_ERR_INT_EN;
+   writel_relaxed(regval, data->base + REG_MMU_INT_CONTROL0);
+
+   regval = F_INT_TRANSLATION_FAULT |
+   F_INT_MAIN_MULTI_HIT_FAULT |
+   F_INT_INVALID_PA_FAULT |
+   F_INT_ENTRY_REPLACEMENT_FAULT |
+   F_INT_TLB_MISS_FAULT |
+   F_INT_MISS_TRANSACTION_FIFO_FAULT |
+   F_INT_PRETETCH_TRANSATION_FIFO_FAULT;
+   writel_relaxed(regval, data->base + REG_MMU_INT_MAIN_CONTROL);
+
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_LEGACY_IVRP_PADDR))
+   regval = (data->protect_base >> 1) | (data->enable_4GB << 31);
+   else
+   regval = lower_32_bits(data->protect_base) |
+upper_32_bits(data->protect_base);
+   writel_relaxed(regval, data->base + REG_MMU_IVRP_PADDR);
+
if (devm_request_irq(data->dev, data->irq, mtk_iommu_isr, 0,
 dev_name(data->dev), (void *)data)) {
writel_relaxed(0, data->base + REG_MMU_PT_BASE_ADDR);
-- 
2.18.0

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


[PATCH v4 24/35] iommu/mediatek: Only adjust code about register base

2022-01-25 Thread Yong Wu
No functional change. Use "base" instead of the data->base. This is
avoid to touch too many lines in the next patches.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 51 +--
 1 file changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 68de89eff9db..fdc14db5b4c0 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -227,12 +227,12 @@ static struct mtk_iommu_domain *to_mtk_domain(struct 
iommu_domain *dom)
 
 static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data *data)
 {
+   void __iomem *base = data->base;
unsigned long flags;
 
spin_lock_irqsave(>tlb_lock, flags);
-   writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
-  data->base + data->plat_data->inv_sel_reg);
-   writel_relaxed(F_ALL_INVLD, data->base + REG_MMU_INVALIDATE);
+   writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0, base + 
data->plat_data->inv_sel_reg);
+   writel_relaxed(F_ALL_INVLD, base + REG_MMU_INVALIDATE);
wmb(); /* Make sure the tlb flush all done */
spin_unlock_irqrestore(>tlb_lock, flags);
 }
@@ -243,6 +243,7 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t size,
struct list_head *head = data->hw_list;
bool check_pm_status;
unsigned long flags;
+   void __iomem *base;
int ret;
u32 tmp;
 
@@ -269,23 +270,23 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t size,
continue;
}
 
+   base = data->base;
+
spin_lock_irqsave(>tlb_lock, flags);
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
-  data->base + data->plat_data->inv_sel_reg);
+  base + data->plat_data->inv_sel_reg);
 
-   writel_relaxed(MTK_IOMMU_TLB_ADDR(iova),
-  data->base + REG_MMU_INVLD_START_A);
+   writel_relaxed(MTK_IOMMU_TLB_ADDR(iova), base + 
REG_MMU_INVLD_START_A);
writel_relaxed(MTK_IOMMU_TLB_ADDR(iova + size - 1),
-  data->base + REG_MMU_INVLD_END_A);
-   writel_relaxed(F_MMU_INV_RANGE,
-  data->base + REG_MMU_INVALIDATE);
+  base + REG_MMU_INVLD_END_A);
+   writel_relaxed(F_MMU_INV_RANGE, base + REG_MMU_INVALIDATE);
 
/* tlb sync */
-   ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE,
+   ret = readl_poll_timeout_atomic(base + REG_MMU_CPE_DONE,
tmp, tmp != 0, 10, 1000);
 
/* Clear the CPE status */
-   writel_relaxed(0, data->base + REG_MMU_CPE_DONE);
+   writel_relaxed(0, base + REG_MMU_CPE_DONE);
spin_unlock_irqrestore(>tlb_lock, flags);
 
if (ret) {
@@ -305,23 +306,25 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
struct mtk_iommu_domain *dom = data->m4u_dom;
unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm 
= 0;
u32 int_state, regval, va34_32, pa34_32;
+   const struct mtk_iommu_plat_data *plat_data = data->plat_data;
+   void __iomem *base = data->base;
u64 fault_iova, fault_pa;
bool layer, write;
 
/* Read error info from registers */
-   int_state = readl_relaxed(data->base + REG_MMU_FAULT_ST1);
+   int_state = readl_relaxed(base + REG_MMU_FAULT_ST1);
if (int_state & F_REG_MMU0_FAULT_MASK) {
-   regval = readl_relaxed(data->base + REG_MMU0_INT_ID);
-   fault_iova = readl_relaxed(data->base + REG_MMU0_FAULT_VA);
-   fault_pa = readl_relaxed(data->base + REG_MMU0_INVLD_PA);
+   regval = readl_relaxed(base + REG_MMU0_INT_ID);
+   fault_iova = readl_relaxed(base + REG_MMU0_FAULT_VA);
+   fault_pa = readl_relaxed(base + REG_MMU0_INVLD_PA);
} else {
-   regval = readl_relaxed(data->base + REG_MMU1_INT_ID);
-   fault_iova = readl_relaxed(data->base + REG_MMU1_FAULT_VA);
-   fault_pa = readl_relaxed(data->base + REG_MMU1_INVLD_PA);
+   regval = readl_relaxed(base + REG_MMU1_INT_ID);
+   fault_iova = readl_relaxed(base + REG_MMU1_FAULT_VA);
+   fault_pa = readl_relaxed(base + REG_MMU1_INVLD_PA);
}
layer = fault_iova & F_MMU_FAULT_VA_LAYER_BIT;
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
-   if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) {
+   if (MTK_IOMMU_HAS_FLAG(plat_data, IOVA_34_EN)) {
va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova);
fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK;
fault_iova |= 

[PATCH v4 22/35] iommu/mediatek: Add PCIe support

2022-01-25 Thread Yong Wu
Currently the code for of_iommu_configure_dev_id is like this:

static int of_iommu_configure_dev_id(struct device_node *master_np,
 struct device *dev,
 const u32 *id)
{
   struct of_phandle_args iommu_spec = { .args_count = 1 };

   err = of_map_id(master_np, *id, "iommu-map",
   "iommu-map-mask", _spec.np,
   iommu_spec.args);
...
}

It supports only one id output. BUT our PCIe HW has two ID(one is for
writing, the other is for reading). I'm not sure if we should change
of_map_id to support output MAX_PHANDLE_ARGS.

Here add the solution in ourselve drivers. If it's pcie case, enable one
more bit.

Not all infra iommu support PCIe, thus add a PCIe support flag here.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 7176c212037f..fe3da530f77e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -134,6 +135,7 @@
 #define MTK_IOMMU_TYPE_MASK(0x3 << 13)
 /* PM and clock always on. e.g. infra iommu */
 #define PM_CLK_AO  BIT(15)
+#define IFA_IOMMU_PCIE_SUPPORT BIT(16)
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x)  (!!(((pdata)->flags) & (_x)))
 
@@ -420,8 +422,11 @@ static int mtk_iommu_config(struct mtk_iommu_data *data, 
struct device *dev,
larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
} else if (MTK_IOMMU_IS_TYPE(data->plat_data, 
MTK_IOMMU_TYPE_INFRA)) {
peri_mmuen_msk = BIT(portid);
-   peri_mmuen = enable ? peri_mmuen_msk : 0;
+   /* PCI dev has only one output id, enable the next 
writing bit for PCIe */
+   if (dev_is_pci(dev))
+   peri_mmuen_msk |= BIT(portid + 1);
 
+   peri_mmuen = enable ? peri_mmuen_msk : 0;
ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1,
 peri_mmuen_msk, peri_mmuen);
if (ret)
@@ -1013,6 +1018,15 @@ static int mtk_iommu_probe(struct platform_device *pdev)
ret = component_master_add_with_match(dev, _iommu_com_ops, 
match);
if (ret)
goto out_bus_set_null;
+   } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) &&
+  MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) 
{
+#ifdef CONFIG_PCI
+   if (!iommu_present(_bus_type)) {
+   ret = bus_set_iommu(_bus_type, _iommu_ops);
+   if (ret) /* PCIe fail don't affect platform_bus. */
+   goto out_list_del;
+   }
+#endif
}
return ret;
 
@@ -1043,6 +1057,11 @@ static int mtk_iommu_remove(struct platform_device *pdev)
if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
device_link_remove(data->smicomm_dev, >dev);
component_master_del(>dev, _iommu_com_ops);
+   } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) &&
+  MTK_IOMMU_HAS_FLAG(data->plat_data, IFA_IOMMU_PCIE_SUPPORT)) 
{
+#ifdef CONFIG_PCI
+   bus_set_iommu(_bus_type, NULL);
+#endif
}
pm_runtime_disable(>dev);
devm_free_irq(>dev, data->irq, data);
-- 
2.18.0

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


[PATCH v4 23/35] iommu/mediatek: Add mt8195 support

2022-01-25 Thread Yong Wu
mt8195 has 3 IOMMU, containing 2 MM IOMMUs, one is for vdo, the other
is for vpp. and 1 INFRA IOMMU.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 43 +++
 drivers/iommu/mtk_iommu.h |  1 +
 2 files changed, 44 insertions(+)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index fe3da530f77e..68de89eff9db 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1195,6 +1195,46 @@ static const struct mtk_iommu_plat_data mt8192_data = {
   {0, 14, 16}, {0, 13, 18, 17}},
 };
 
+static const struct mtk_iommu_plat_data mt8195_data_infra = {
+   .m4u_plat = M4U_MT8195,
+   .flags= WR_THROT_EN | DCM_DISABLE | PM_CLK_AO |
+   MTK_IOMMU_TYPE_INFRA | IFA_IOMMU_PCIE_SUPPORT,
+   .pericfg_comp_str = "mediatek,mt8195-pericfg_ao",
+   .inv_sel_reg  = REG_MMU_INV_SEL_GEN2,
+   .iova_region  = single_domain,
+   .iova_region_nr   = ARRAY_SIZE(single_domain),
+};
+
+static const struct mtk_iommu_plat_data mt8195_data_vdo = {
+   .m4u_plat   = M4U_MT8195,
+   .flags  = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
+ WR_THROT_EN | NOT_STD_AXI_MODE | IOVA_34_EN |
+ SHARE_PGTABLE | MTK_IOMMU_TYPE_MM,
+   .hw_list= ,
+   .inv_sel_reg= REG_MMU_INV_SEL_GEN2,
+   .iova_region= mt8192_multi_dom,
+   .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
+   .larbid_remap   = {{2, 0}, {21}, {24}, {7}, {19}, {9, 10, 11},
+  {13, 17, 15/* 17b */, 25}, {5}},
+};
+
+static const struct mtk_iommu_plat_data mt8195_data_vpp = {
+   .m4u_plat   = M4U_MT8195,
+   .flags  = HAS_BCLK | HAS_SUB_COMM_3BITS | OUT_ORDER_WR_EN |
+ WR_THROT_EN | NOT_STD_AXI_MODE | IOVA_34_EN |
+ SHARE_PGTABLE | MTK_IOMMU_TYPE_MM,
+   .hw_list= ,
+   .inv_sel_reg= REG_MMU_INV_SEL_GEN2,
+   .iova_region= mt8192_multi_dom,
+   .iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
+   .larbid_remap   = {{1}, {3},
+  {22, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 
MTK_INVALID_LARBID, 23},
+  {8}, {20}, {12},
+  /* 16: 16a; 29: 16b; 30: CCUtop0; 31: CCUtop1 */
+  {14, 16, 29, 26, 30, 31, 18},
+  {4, MTK_INVALID_LARBID, MTK_INVALID_LARBID, 
MTK_INVALID_LARBID, 6}},
+};
+
 static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt2712-m4u", .data = _data},
{ .compatible = "mediatek,mt6779-m4u", .data = _data},
@@ -1202,6 +1242,9 @@ static const struct of_device_id mtk_iommu_of_ids[] = {
{ .compatible = "mediatek,mt8173-m4u", .data = _data},
{ .compatible = "mediatek,mt8183-m4u", .data = _data},
{ .compatible = "mediatek,mt8192-m4u", .data = _data},
+   { .compatible = "mediatek,mt8195-iommu-infra", .data = 
_data_infra},
+   { .compatible = "mediatek,mt8195-iommu-vdo",   .data = 
_data_vdo},
+   { .compatible = "mediatek,mt8195-iommu-vpp",   .data = 
_data_vpp},
{}
 };
 
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 04e5e5e7fd62..9dba98bb12eb 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -46,6 +46,7 @@ enum mtk_iommu_plat {
M4U_MT8173,
M4U_MT8183,
M4U_MT8192,
+   M4U_MT8195,
 };
 
 struct mtk_iommu_iova_region;
-- 
2.18.0

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


[PATCH v4 21/35] iommu/mediatek: Add infra iommu support

2022-01-25 Thread Yong Wu
The infra iommu enable bits in mt8195 is in the pericfg register segment,
use regmap to update it.

If infra iommu master translation fault, It doesn't have the larbid/portid,
thus print out the whole register value.

Since regmap_update_bits may fail, add return value for mtk_iommu_config.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 36 +---
 drivers/iommu/mtk_iommu.h |  2 ++
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 531f4750c721..7176c212037f 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -112,6 +112,8 @@
 
 #define MTK_PROTECT_PA_ALIGN   256
 
+#define PERICFG_IOMMU_10x714
+
 #define HAS_4GB_MODE   BIT(0)
 /* HW will use the EMI clock if there isn't the "bclk". */
 #define HAS_BCLK   BIT(1)
@@ -343,8 +345,8 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
   write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
dev_err_ratelimited(
data->dev,
-   "fault type=0x%x iova=0x%llx pa=0x%llx larb=%d port=%d 
layer=%d %s\n",
-   int_state, fault_iova, fault_pa, fault_larb, fault_port,
+   "fault type=0x%x iova=0x%llx pa=0x%llx 
master=0x%x(larb=%d port=%d) layer=%d %s\n",
+   int_state, fault_iova, fault_pa, regval, fault_larb, 
fault_port,
layer, write ? "write" : "read");
}
 
@@ -388,14 +390,15 @@ static int mtk_iommu_get_domain_id(struct device *dev,
return -EINVAL;
 }
 
-static void mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
-bool enable, unsigned int domid)
+static int mtk_iommu_config(struct mtk_iommu_data *data, struct device *dev,
+   bool enable, unsigned int domid)
 {
struct mtk_smi_larb_iommu*larb_mmu;
unsigned int larbid, portid;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
const struct mtk_iommu_iova_region *region;
-   int i;
+   u32 peri_mmuen, peri_mmuen_msk;
+   int i, ret = 0;
 
for (i = 0; i < fwspec->num_ids; ++i) {
larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
@@ -415,8 +418,19 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, 
struct device *dev,
larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
else
larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+   } else if (MTK_IOMMU_IS_TYPE(data->plat_data, 
MTK_IOMMU_TYPE_INFRA)) {
+   peri_mmuen_msk = BIT(portid);
+   peri_mmuen = enable ? peri_mmuen_msk : 0;
+
+   ret = regmap_update_bits(data->pericfg, PERICFG_IOMMU_1,
+peri_mmuen_msk, peri_mmuen);
+   if (ret)
+   dev_err(dev, "%s iommu(%s) inframaster 0x%x 
fail(%d).\n",
+   enable ? "enable" : "disable",
+   dev_name(data->dev), peri_mmuen_msk, 
ret);
}
}
+   return ret;
 }
 
 static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
@@ -531,8 +545,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
}
mutex_unlock(>mutex);
 
-   mtk_iommu_config(data, dev, true, domid);
-   return 0;
+   return mtk_iommu_config(data, dev, true, domid);
 
 data_unlock:
mutex_unlock(>mutex);
@@ -956,6 +969,15 @@ static int mtk_iommu_probe(struct platform_device *pdev)
ret = mtk_iommu_mm_dts_parse(dev, , data);
if (ret)
goto out_runtime_disable;
+   } else if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_INFRA) &&
+  data->plat_data->pericfg_comp_str) {
+   infracfg = 
syscon_regmap_lookup_by_compatible(data->plat_data->pericfg_comp_str);
+   if (IS_ERR(infracfg)) {
+   ret = PTR_ERR(infracfg);
+   goto out_runtime_disable;
+   }
+
+   data->pericfg = infracfg;
}
 
platform_set_drvdata(pdev, data);
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 82c51a034e6b..04e5e5e7fd62 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -55,6 +55,7 @@ struct mtk_iommu_plat_data {
u32 flags;
u32 inv_sel_reg;
 
+   char*pericfg_comp_str;
struct list_head*hw_list;
unsigned intiova_region_nr;
const 

[PATCH v4 20/35] iommu/mediatek: Add a PM_CLK_AO flag for infra iommu

2022-01-25 Thread Yong Wu
The power/clock of infra iommu is always on, and it doesn't have the
device link with the master devices, then the infra iommu device's pm
statua is not active, thus we add A PM_CLK_AO flag for infra iommu.

The tlb operation is a bit not clear in this file, Comment them in the
code here.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 29 ++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index cf042ab74fa7..531f4750c721 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -130,6 +130,8 @@
 #define MTK_IOMMU_TYPE_MM  (0x0 << 13)
 #define MTK_IOMMU_TYPE_INFRA   (0x1 << 13)
 #define MTK_IOMMU_TYPE_MASK(0x3 << 13)
+/* PM and clock always on. e.g. infra iommu */
+#define PM_CLK_AO  BIT(15)
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x)  (!!(((pdata)->flags) & (_x)))
 
@@ -235,13 +237,33 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t size,
   struct mtk_iommu_data *data)
 {
struct list_head *head = data->hw_list;
+   bool check_pm_status;
unsigned long flags;
int ret;
u32 tmp;
 
for_each_m4u(data, head) {
-   if (pm_runtime_get_if_in_use(data->dev) <= 0)
-   continue;
+   /*
+* To avoid resume the iommu device frequently when the iommu 
device
+* is not active, it doesn't always call pm_runtime_get here, 
then tlb
+* flush depends on the tlb flush all in the runtime resume.
+*
+* There are 2 special cases:
+*
+* Case1: The iommu dev doesn't have power domain but has bclk. 
This case
+* should also avoid the tlb flush while the dev is not active 
to mute
+* the tlb timeout log. like mt8173.
+*
+* Case2: The power/clock of infra iommu is always on, and it 
doesn't
+* have the device link with the master devices. This case 
should avoid
+* the PM status check.
+*/
+   check_pm_status = !MTK_IOMMU_HAS_FLAG(data->plat_data, 
PM_CLK_AO);
+
+   if (check_pm_status) {
+   if (pm_runtime_get_if_in_use(data->dev) <= 0)
+   continue;
+   }
 
spin_lock_irqsave(>tlb_lock, flags);
writel_relaxed(F_INVLD_EN1 | F_INVLD_EN0,
@@ -268,7 +290,8 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t size,
mtk_iommu_tlb_flush_all(data);
}
 
-   pm_runtime_put(data->dev);
+   if (check_pm_status)
+   pm_runtime_put(data->dev);
}
 }
 
-- 
2.18.0

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


[PATCH v4 19/35] iommu/mediatek: Allow IOMMU_DOMAIN_UNMANAGED for PCIe VFIO

2022-01-25 Thread Yong Wu
Allow the type IOMMU_DOMAIN_UNMANAGED since vfio_iommu_type1.c always call
iommu_domain_alloc. The PCIe EP works ok when going through vfio.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index f676085af13d..cf042ab74fa7 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -446,7 +446,7 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned 
type)
 {
struct mtk_iommu_domain *dom;
 
-   if (type != IOMMU_DOMAIN_DMA)
+   if (type != IOMMU_DOMAIN_DMA && type != IOMMU_DOMAIN_UNMANAGED)
return NULL;
 
dom = kzalloc(sizeof(*dom), GFP_KERNEL);
-- 
2.18.0

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


[PATCH v4 18/35] iommu/mediatek: Adjust device link when it is sub-common

2022-01-25 Thread Yong Wu
For MM IOMMU, We always add device link between smi-common and IOMMU HW.
In mt8195, we add smi-sub-common. Thus, if the node is sub-common, we still
need find again to get smi-common, then do device link.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 18 ++
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 71f3acd00d8c..f676085af13d 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -798,9 +798,9 @@ static int mtk_iommu_mm_dts_parse(struct device *dev,
  struct component_match **match,
  struct mtk_iommu_data *data)
 {
+   struct device_node *larbnode, *smicomm_node, *smi_subcomm_node;
struct platform_device  *plarbdev;
struct device_link  *link;
-   struct device_node *larbnode, *smicomm_node;
int i, larb_nr, ret;
 
larb_nr = of_count_phandle_with_args(dev->of_node, "mediatek,larbs", 
NULL);
@@ -834,11 +834,21 @@ static int mtk_iommu_mm_dts_parse(struct device *dev,
compare_of, larbnode);
}
 
-   /* Get smi-common dev from the last larb. */
-   smicomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
-   if (!smicomm_node)
+   /* Get smi-(sub)-common dev from the last larb. */
+   smi_subcomm_node = of_parse_phandle(larbnode, "mediatek,smi", 0);
+   if (!smi_subcomm_node)
return -EINVAL;
 
+   /*
+* It may have two level smi-common. the node is smi-sub-common if it
+* has a new mediatek,smi property. otherwise it is smi-commmon.
+*/
+   smicomm_node = of_parse_phandle(smi_subcomm_node, "mediatek,smi", 0);
+   if (smicomm_node)
+   of_node_put(smi_subcomm_node);
+   else
+   smicomm_node = smi_subcomm_node;
+
plarbdev = of_find_device_by_node(smicomm_node);
of_node_put(smicomm_node);
data->smicomm_dev = >dev;
-- 
2.18.0

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


[PATCH v4 17/35] iommu/mediatek: Contain MM IOMMU flow with the MM TYPE

2022-01-25 Thread Yong Wu
Prepare for supporting INFRA_IOMMU, and APU_IOMMU later.

For Infra IOMMU/APU IOMMU, it doesn't have the "larb""port". thus, Use
the MM flag contain the MM_IOMMU special flow, Also, it moves a big
chunk code about parsing the mediatek,larbs into a function, this is
only needed for MM IOMMU. and all the current SoC are MM_IOMMU.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 195 ++
 1 file changed, 111 insertions(+), 84 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 418ec0b7a43b..71f3acd00d8c 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -138,6 +138,8 @@
 #define MTK_IOMMU_IS_TYPE(pdata, _x)   MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\
MTK_IOMMU_TYPE_MASK)
 
+#define MTK_INVALID_LARBID MTK_LARB_NR_MAX
+
 struct mtk_iommu_domain {
struct io_pgtable_cfg   cfg;
struct io_pgtable_ops   *iop;
@@ -274,7 +276,7 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
 {
struct mtk_iommu_data *data = dev_id;
struct mtk_iommu_domain *dom = data->m4u_dom;
-   unsigned int fault_larb, fault_port, sub_comm = 0;
+   unsigned int fault_larb = MTK_INVALID_LARBID, fault_port = 0, sub_comm 
= 0;
u32 int_state, regval, va34_32, pa34_32;
u64 fault_iova, fault_pa;
bool layer, write;
@@ -300,17 +302,19 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
fault_pa |= (u64)pa34_32 << 32;
 
-   fault_port = F_MMU_INT_ID_PORT_ID(regval);
-   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
-   fault_larb = F_MMU_INT_ID_COMM_ID(regval);
-   sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
-   } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) {
-   fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval);
-   sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval);
-   } else {
-   fault_larb = F_MMU_INT_ID_LARB_ID(regval);
+   if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+   fault_port = F_MMU_INT_ID_PORT_ID(regval);
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
+   fault_larb = F_MMU_INT_ID_COMM_ID(regval);
+   sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
+   } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, 
HAS_SUB_COMM_3BITS)) {
+   fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval);
+   sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval);
+   } else {
+   fault_larb = F_MMU_INT_ID_LARB_ID(regval);
+   }
+   fault_larb = 
data->plat_data->larbid_remap[fault_larb][sub_comm];
}
-   fault_larb = data->plat_data->larbid_remap[fault_larb][sub_comm];
 
if (report_iommu_fault(>domain, data->dev, fault_iova,
   write ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ)) {
@@ -374,19 +378,21 @@ static void mtk_iommu_config(struct mtk_iommu_data *data, 
struct device *dev,
larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
portid = MTK_M4U_TO_PORT(fwspec->ids[i]);
 
-   larb_mmu = >larb_imu[larbid];
+   if (MTK_IOMMU_IS_TYPE(data->plat_data, MTK_IOMMU_TYPE_MM)) {
+   larb_mmu = >larb_imu[larbid];
 
-   region = data->plat_data->iova_region + domid;
-   larb_mmu->bank[portid] = upper_32_bits(region->iova_base);
+   region = data->plat_data->iova_region + domid;
+   larb_mmu->bank[portid] = 
upper_32_bits(region->iova_base);
 
-   dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank %d.\n",
-   enable ? "enable" : "disable", dev_name(larb_mmu->dev),
-   portid, domid, larb_mmu->bank[portid]);
+   dev_dbg(dev, "%s iommu for larb(%s) port %d dom %d bank 
%d.\n",
+   enable ? "enable" : "disable", 
dev_name(larb_mmu->dev),
+   portid, domid, larb_mmu->bank[portid]);
 
-   if (enable)
-   larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
-   else
-   larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+   if (enable)
+   larb_mmu->mmu |= MTK_SMI_MMU_EN(portid);
+   else
+   larb_mmu->mmu &= ~MTK_SMI_MMU_EN(portid);
+   }
}
 }
 
@@ -788,19 +794,75 @@ static const struct component_master_ops 
mtk_iommu_com_ops = {
.unbind = mtk_iommu_unbind,
 };
 
+static int mtk_iommu_mm_dts_parse(struct device *dev,
+

[PATCH v4 16/35] iommu/mediatek: Add IOMMU_TYPE flag

2022-01-25 Thread Yong Wu
Add IOMMU_TYPE definition. In the mt8195, we have another IOMMU_TYPE:
infra iommu, also there will be another APU_IOMMU, thus, use 2bits for the
IOMMU_TYPE.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 47d5f34f4db0..418ec0b7a43b 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -126,9 +126,17 @@
 #define SHARE_PGTABLE  BIT(10) /* 2 HW share pgtable */
 #define DCM_DISABLEBIT(11)
 #define NOT_STD_AXI_MODE   BIT(12)
+/* 2 bits: iommu type */
+#define MTK_IOMMU_TYPE_MM  (0x0 << 13)
+#define MTK_IOMMU_TYPE_INFRA   (0x1 << 13)
+#define MTK_IOMMU_TYPE_MASK(0x3 << 13)
 
-#define MTK_IOMMU_HAS_FLAG(pdata, _x) \
-   pdata)->flags) & (_x)) == (_x))
+#define MTK_IOMMU_HAS_FLAG(pdata, _x)  (!!(((pdata)->flags) & (_x)))
+
+#define MTK_IOMMU_HAS_FLAG_MASK(pdata, _x, mask)   \
+   pdata)->flags) & (mask)) == (_x))
+#define MTK_IOMMU_IS_TYPE(pdata, _x)   MTK_IOMMU_HAS_FLAG_MASK(pdata, _x,\
+   MTK_IOMMU_TYPE_MASK)
 
 struct mtk_iommu_domain {
struct io_pgtable_cfg   cfg;
-- 
2.18.0

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


[PATCH v4 15/35] iommu/mediatek: Add SUB_COMMON_3BITS flag

2022-01-25 Thread Yong Wu
In prevous SoC, the sub common id occupy 2 bits. the mt8195's sub common
id has 3bits. Add a new flag for this. and rename the previous flag to
_2BITS. For readable, I put these two flags together, then move the
other flags. no functional change.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 26 --
 drivers/iommu/mtk_iommu.h |  2 +-
 2 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 548fa8448a6e..47d5f34f4db0 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -105,6 +105,8 @@
 #define REG_MMU1_INT_ID0x154
 #define F_MMU_INT_ID_COMM_ID(a)(((a) >> 9) & 0x7)
 #define F_MMU_INT_ID_SUB_COMM_ID(a)(((a) >> 7) & 0x3)
+#define F_MMU_INT_ID_COMM_ID_EXT(a)(((a) >> 10) & 0x7)
+#define F_MMU_INT_ID_SUB_COMM_ID_EXT(a)(((a) >> 7) & 0x7)
 #define F_MMU_INT_ID_LARB_ID(a)(((a) >> 7) & 0x7)
 #define F_MMU_INT_ID_PORT_ID(a)(((a) >> 2) & 0x1f)
 
@@ -116,13 +118,14 @@
 #define HAS_VLD_PA_RNG BIT(2)
 #define RESET_AXI  BIT(3)
 #define OUT_ORDER_WR_ENBIT(4)
-#define HAS_SUB_COMM   BIT(5)
-#define WR_THROT_ENBIT(6)
-#define HAS_LEGACY_IVRP_PADDR  BIT(7)
-#define IOVA_34_EN BIT(8)
-#define SHARE_PGTABLE  BIT(9) /* 2 HW share pgtable */
-#define DCM_DISABLEBIT(10)
-#define NOT_STD_AXI_MODE   BIT(11)
+#define HAS_SUB_COMM_2BITS BIT(5)
+#define HAS_SUB_COMM_3BITS BIT(6)
+#define WR_THROT_ENBIT(7)
+#define HAS_LEGACY_IVRP_PADDR  BIT(8)
+#define IOVA_34_EN BIT(9)
+#define SHARE_PGTABLE  BIT(10) /* 2 HW share pgtable */
+#define DCM_DISABLEBIT(11)
+#define NOT_STD_AXI_MODE   BIT(12)
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x) \
pdata)->flags) & (_x)) == (_x))
@@ -290,9 +293,12 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
fault_pa |= (u64)pa34_32 << 32;
 
fault_port = F_MMU_INT_ID_PORT_ID(regval);
-   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) {
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_2BITS)) {
fault_larb = F_MMU_INT_ID_COMM_ID(regval);
sub_comm = F_MMU_INT_ID_SUB_COMM_ID(regval);
+   } else if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM_3BITS)) {
+   fault_larb = F_MMU_INT_ID_COMM_ID_EXT(regval);
+   sub_comm = F_MMU_INT_ID_SUB_COMM_ID_EXT(regval);
} else {
fault_larb = F_MMU_INT_ID_LARB_ID(regval);
}
@@ -1033,7 +1039,7 @@ static const struct mtk_iommu_plat_data mt2712_data = {
 
 static const struct mtk_iommu_plat_data mt6779_data = {
.m4u_plat  = M4U_MT6779,
-   .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN |
+   .flags = HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN | WR_THROT_EN |
 NOT_STD_AXI_MODE,
.inv_sel_reg   = REG_MMU_INV_SEL_GEN2,
.iova_region   = single_domain,
@@ -1071,7 +1077,7 @@ static const struct mtk_iommu_plat_data mt8183_data = {
 
 static const struct mtk_iommu_plat_data mt8192_data = {
.m4u_plat   = M4U_MT8192,
-   .flags  = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN |
+   .flags  = HAS_BCLK | HAS_SUB_COMM_2BITS | OUT_ORDER_WR_EN |
  WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE,
.inv_sel_reg= REG_MMU_INV_SEL_GEN2,
.iova_region= mt8192_multi_dom,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index c10f5630e55d..82c51a034e6b 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -20,7 +20,7 @@
 #include 
 
 #define MTK_LARB_COM_MAX   8
-#define MTK_LARB_SUBCOM_MAX4
+#define MTK_LARB_SUBCOM_MAX8
 
 #define MTK_IOMMU_GROUP_MAX8
 
-- 
2.18.0

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


[PATCH v4 14/35] iommu/mediatek: Always enable output PA over 32bits in isr

2022-01-25 Thread Yong Wu
Currently the output PA[32:33] is contained by the flag IOVA_34.
This is not right. the iova_34 has no relation with pa[32:33], the 32bits
iova still could map to pa[32:33]. Move it out from the flag.

No need fix tag since currently only mt8192 use the calulation and it
always has this IOVA_34 flag.

Prepare for the IOMMU that still use IOVA 32bits but its dram size may be
over 4GB.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 028b2192c414..548fa8448a6e 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -283,11 +283,11 @@ static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
write = fault_iova & F_MMU_FAULT_VA_WRITE_BIT;
if (MTK_IOMMU_HAS_FLAG(data->plat_data, IOVA_34_EN)) {
va34_32 = FIELD_GET(F_MMU_INVAL_VA_34_32_MASK, fault_iova);
-   pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
fault_iova = fault_iova & F_MMU_INVAL_VA_31_12_MASK;
fault_iova |= (u64)va34_32 << 32;
-   fault_pa |= (u64)pa34_32 << 32;
}
+   pa34_32 = FIELD_GET(F_MMU_INVAL_PA_34_32_MASK, fault_iova);
+   fault_pa |= (u64)pa34_32 << 32;
 
fault_port = F_MMU_INT_ID_PORT_ID(regval);
if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_SUB_COMM)) {
-- 
2.18.0

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


[PATCH v4 13/35] iommu/mediatek: Remove the granule in the tlb flush

2022-01-25 Thread Yong Wu
The MediaTek IOMMU don't care about granule when tlb flushing.
Remove this variable.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 80d8333797fd..028b2192c414 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -219,7 +219,6 @@ static void mtk_iommu_tlb_flush_all(struct mtk_iommu_data 
*data)
 }
 
 static void mtk_iommu_tlb_flush_range_sync(unsigned long iova, size_t size,
-  size_t granule,
   struct mtk_iommu_data *data)
 {
struct list_head *head = data->hw_list;
@@ -541,8 +540,7 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain 
*domain,
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
size_t length = gather->end - gather->start + 1;
 
-   mtk_iommu_tlb_flush_range_sync(gather->start, length, gather->pgsize,
-  dom->data);
+   mtk_iommu_tlb_flush_range_sync(gather->start, length, dom->data);
 }
 
 static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
@@ -550,7 +548,7 @@ static void mtk_iommu_sync_map(struct iommu_domain *domain, 
unsigned long iova,
 {
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
 
-   mtk_iommu_tlb_flush_range_sync(iova, size, size, dom->data);
+   mtk_iommu_tlb_flush_range_sync(iova, size, dom->data);
 }
 
 static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
-- 
2.18.0

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


[PATCH v4 12/35] iommu/mediatek: Add a flag NON_STD_AXI

2022-01-25 Thread Yong Wu
Add a new flag NON_STD_AXI, All the previous SoC support this flag.
Prepare for adding infra and apu iommu which don't support this.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index b2361e8b06d9..80d8333797fd 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -122,6 +122,7 @@
 #define IOVA_34_EN BIT(8)
 #define SHARE_PGTABLE  BIT(9) /* 2 HW share pgtable */
 #define DCM_DISABLEBIT(10)
+#define NOT_STD_AXI_MODE   BIT(11)
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x) \
pdata)->flags) & (_x)) == (_x))
@@ -753,7 +754,8 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
regval = 0;
} else {
regval = readl_relaxed(data->base + REG_MMU_MISC_CTRL);
-   regval &= ~F_MMU_STANDARD_AXI_MODE_MASK;
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, NOT_STD_AXI_MODE))
+   regval &= ~F_MMU_STANDARD_AXI_MODE_MASK;
if (MTK_IOMMU_HAS_FLAG(data->plat_data, OUT_ORDER_WR_EN))
regval &= ~F_MMU_IN_ORDER_WR_EN_MASK;
}
@@ -1022,7 +1024,8 @@ static const struct dev_pm_ops mtk_iommu_pm_ops = {
 
 static const struct mtk_iommu_plat_data mt2712_data = {
.m4u_plat = M4U_MT2712,
-   .flags= HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | 
SHARE_PGTABLE,
+   .flags= HAS_4GB_MODE | HAS_BCLK | HAS_VLD_PA_RNG | 
SHARE_PGTABLE |
+   NOT_STD_AXI_MODE,
.hw_list  = ,
.inv_sel_reg  = REG_MMU_INV_SEL_GEN1,
.iova_region  = single_domain,
@@ -1032,7 +1035,8 @@ static const struct mtk_iommu_plat_data mt2712_data = {
 
 static const struct mtk_iommu_plat_data mt6779_data = {
.m4u_plat  = M4U_MT6779,
-   .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN,
+   .flags = HAS_SUB_COMM | OUT_ORDER_WR_EN | WR_THROT_EN |
+NOT_STD_AXI_MODE,
.inv_sel_reg   = REG_MMU_INV_SEL_GEN2,
.iova_region   = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1041,7 +1045,7 @@ static const struct mtk_iommu_plat_data mt6779_data = {
 
 static const struct mtk_iommu_plat_data mt8167_data = {
.m4u_plat = M4U_MT8167,
-   .flags= RESET_AXI | HAS_LEGACY_IVRP_PADDR,
+   .flags= RESET_AXI | HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE,
.inv_sel_reg  = REG_MMU_INV_SEL_GEN1,
.iova_region  = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1051,7 +1055,7 @@ static const struct mtk_iommu_plat_data mt8167_data = {
 static const struct mtk_iommu_plat_data mt8173_data = {
.m4u_plat = M4U_MT8173,
.flags= HAS_4GB_MODE | HAS_BCLK | RESET_AXI |
-   HAS_LEGACY_IVRP_PADDR,
+   HAS_LEGACY_IVRP_PADDR | NOT_STD_AXI_MODE,
.inv_sel_reg  = REG_MMU_INV_SEL_GEN1,
.iova_region  = single_domain,
.iova_region_nr = ARRAY_SIZE(single_domain),
@@ -1070,7 +1074,7 @@ static const struct mtk_iommu_plat_data mt8183_data = {
 static const struct mtk_iommu_plat_data mt8192_data = {
.m4u_plat   = M4U_MT8192,
.flags  = HAS_BCLK | HAS_SUB_COMM | OUT_ORDER_WR_EN |
- WR_THROT_EN | IOVA_34_EN,
+ WR_THROT_EN | IOVA_34_EN | NOT_STD_AXI_MODE,
.inv_sel_reg= REG_MMU_INV_SEL_GEN2,
.iova_region= mt8192_multi_dom,
.iova_region_nr = ARRAY_SIZE(mt8192_multi_dom),
-- 
2.18.0

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


[PATCH v4 11/35] iommu/mediatek: Add a flag DCM_DISABLE

2022-01-25 Thread Yong Wu
In the infra iommu, we should disable DCM. add a new flag for this.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 4a24977274e3..b2361e8b06d9 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -51,6 +51,8 @@
 #define F_MMU_STANDARD_AXI_MODE_MASK   (BIT(3) | BIT(19))
 
 #define REG_MMU_DCM_DIS0x050
+#define F_MMU_DCM  BIT(8)
+
 #define REG_MMU_WR_LEN_CTRL0x054
 #define F_MMU_WR_THROT_DIS_MASK(BIT(5) | BIT(21))
 
@@ -119,6 +121,7 @@
 #define HAS_LEGACY_IVRP_PADDR  BIT(7)
 #define IOVA_34_EN BIT(8)
 #define SHARE_PGTABLE  BIT(9) /* 2 HW share pgtable */
+#define DCM_DISABLEBIT(10)
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x) \
pdata)->flags) & (_x)) == (_x))
@@ -733,7 +736,11 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
regval = F_MMU_VLD_PA_RNG(7, 4);
writel_relaxed(regval, data->base + REG_MMU_VLD_PA_RNG);
}
-   writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, DCM_DISABLE))
+   writel_relaxed(F_MMU_DCM, data->base + REG_MMU_DCM_DIS);
+   else
+   writel_relaxed(0, data->base + REG_MMU_DCM_DIS);
+
if (MTK_IOMMU_HAS_FLAG(data->plat_data, WR_THROT_EN)) {
/* write command throttling mode */
regval = readl_relaxed(data->base + REG_MMU_WR_LEN_CTRL);
-- 
2.18.0

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


[PATCH v4 10/35] iommu/mediatek: Add 12G~16G support for multi domains

2022-01-25 Thread Yong Wu
In mt8192, we preassign 0-4G; 4G-8G; 8G-12G for different multimedia
engines. This depends on the "dma-ranges=" in the iommu consumer's dtsi
node.

Adds 12G-16G region here. and reword the previous comment. we don't limit
which master locate in which region.

CCU still is 8G-12G. Don't change it here.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 1712f5fcdcab..4a24977274e3 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -180,10 +180,12 @@ static const struct mtk_iommu_iova_region single_domain[] 
= {
 };
 
 static const struct mtk_iommu_iova_region mt8192_multi_dom[] = {
-   { .iova_base = 0x0, .size = SZ_4G}, /* disp: 0 ~ 4G 
*/
+   { .iova_base = 0x0, .size = SZ_4G}, /* 0 ~ 4G */
#if IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT)
-   { .iova_base = SZ_4G,   .size = SZ_4G}, /* vdec: 4G ~ 
8G */
-   { .iova_base = SZ_4G * 2,   .size = SZ_4G}, /* CAM/MDP: 8G 
~ 12G */
+   { .iova_base = SZ_4G,   .size = SZ_4G}, /* 4G ~ 8G */
+   { .iova_base = SZ_4G * 2,   .size = SZ_4G}, /* 8G ~ 12G */
+   { .iova_base = SZ_4G * 3,   .size = SZ_4G}, /* 12G ~ 16G */
+
{ .iova_base = 0x24000ULL,  .size = 0x400}, /* CCU0 */
{ .iova_base = 0x24400ULL,  .size = 0x400}, /* CCU1 */
#endif
-- 
2.18.0

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


[PATCH v4 09/35] iommu/mediatek: Adapt sharing and non-sharing pgtable case

2022-01-25 Thread Yong Wu
In previous mt2712, Both IOMMUs are MM IOMMU, and they will share pgtable.
However in the latest SoC, another is infra IOMMU, there is no reason to
share pgtable between MM with INFRA IOMMU. This patch manage to
implement the two case(sharing and non-sharing pgtable).

Currently we use for_each_m4u to loop the 2 HWs. Add the list_head into
this macro.
In the sharing pgtable case, the list_head is the global "m4ulist".
In the non-sharing pgtable case, the list_head is hw_list_head which is a
variable in the "data". then for_each_m4u will only loop itself.

Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 43 +--
 drivers/iommu/mtk_iommu.h |  7 +++
 2 files changed, 30 insertions(+), 20 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index d982dfd815c6..1712f5fcdcab 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -118,6 +118,7 @@
 #define WR_THROT_ENBIT(6)
 #define HAS_LEGACY_IVRP_PADDR  BIT(7)
 #define IOVA_34_EN BIT(8)
+#define SHARE_PGTABLE  BIT(9) /* 2 HW share pgtable */
 
 #define MTK_IOMMU_HAS_FLAG(pdata, _x) \
pdata)->flags) & (_x)) == (_x))
@@ -167,7 +168,7 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data);
 
 static LIST_HEAD(m4ulist); /* List all the M4U HWs */
 
-#define for_each_m4u(data) list_for_each_entry(data, , list)
+#define for_each_m4u(data, head)  list_for_each_entry(data, head, list)
 
 struct mtk_iommu_iova_region {
dma_addr_t  iova_base;
@@ -188,21 +189,10 @@ static const struct mtk_iommu_iova_region 
mt8192_multi_dom[] = {
#endif
 };
 
-/*
- * There may be 1 or 2 M4U HWs, But we always expect they are in the same 
domain
- * for the performance.
- *
- * Here always return the mtk_iommu_data of the first probed M4U where the
- * iommu domain information is recorded.
- */
-static struct mtk_iommu_data *mtk_iommu_get_m4u_data(void)
+/* If 2 M4U share a domain(use the same hwlist), Put the corresponding info in 
first data.*/
+static struct mtk_iommu_data *mtk_iommu_get_frst_data(struct list_head *hwlist)
 {
-   struct mtk_iommu_data *data;
-
-   for_each_m4u(data)
-   return data;
-
-   return NULL;
+   return list_first_entry(hwlist, struct mtk_iommu_data, list);
 }
 
 static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
@@ -226,11 +216,12 @@ static void mtk_iommu_tlb_flush_range_sync(unsigned long 
iova, size_t size,
   size_t granule,
   struct mtk_iommu_data *data)
 {
+   struct list_head *head = data->hw_list;
unsigned long flags;
int ret;
u32 tmp;
 
-   for_each_m4u(data) {
+   for_each_m4u(data, head) {
if (pm_runtime_get_if_in_use(data->dev) <= 0)
continue;
 
@@ -451,6 +442,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
 {
struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata;
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
+   struct list_head *hw_list = data->hw_list;
struct device *m4udev = data->dev;
int ret, domid;
 
@@ -461,7 +453,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
mutex_lock(>mutex);
if (!dom->data) {
/* Data is in the frstdata in sharing pgtable case. */
-   frstdata = mtk_iommu_get_m4u_data();
+   frstdata = mtk_iommu_get_frst_data(hw_list);
 
ret = mtk_iommu_domain_finalise(dom, frstdata, domid);
if (ret) {
@@ -595,10 +587,12 @@ static void mtk_iommu_release_device(struct device *dev)
 
 static struct iommu_group *mtk_iommu_device_group(struct device *dev)
 {
-   struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+   struct mtk_iommu_data *c_data = dev_iommu_priv_get(dev), *data;
+   struct list_head *hw_list = c_data->hw_list;
struct iommu_group *group;
int domid;
 
+   data = mtk_iommu_get_frst_data(hw_list);
if (!data)
return ERR_PTR(-ENODEV);
 
@@ -902,7 +896,15 @@ static int mtk_iommu_probe(struct platform_device *pdev)
goto out_sysfs_remove;
 
spin_lock_init(>tlb_lock);
-   list_add_tail(>list, );
+
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) {
+   list_add_tail(>list, data->plat_data->hw_list);
+   data->hw_list = data->plat_data->hw_list;
+   } else {
+   INIT_LIST_HEAD(>hw_list_head);
+   list_add_tail(>list, >hw_list_head);
+   data->hw_list = >hw_list_head;
+   }
 
if (!iommu_present(_bus_type)) {
ret = bus_set_iommu(_bus_type, _iommu_ops);
@@ -1011,7 +1013,8 @@ static const struct 

[PATCH v4 08/35] iommu/mediatek: Use kmalloc for protect buffer

2022-01-25 Thread Yong Wu
No need zero for the protect buffer that is only accessed by the IOMMU HW
translation fault happened.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index e6e4ee471867..d982dfd815c6 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -794,7 +794,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
data->plat_data = of_device_get_match_data(dev);
 
/* Protect memory. HW will access here while translation fault.*/
-   protect = devm_kzalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
+   protect = devm_kmalloc(dev, MTK_PROTECT_PA_ALIGN * 2, GFP_KERNEL);
if (!protect)
return -ENOMEM;
data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
-- 
2.18.0

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


[PATCH v4 07/35] iommu/mediatek: Add mutex for data in the mtk_iommu_domain

2022-01-25 Thread Yong Wu
Same with the previous patch, add a mutex for the "data" in the
mtk_iommu_domain. Just improve the safety for multi devices
enter attach_device at the same time. We don't get the real issue
for this.

Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 095736bfb7b4..e6e4ee471867 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -128,6 +128,8 @@ struct mtk_iommu_domain {
 
struct mtk_iommu_data   *data;
struct iommu_domain domain;
+
+   struct mutexmutex; /* Protect "data" in this 
structure */
 };
 
 static const struct iommu_ops mtk_iommu_ops;
@@ -434,6 +436,7 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned 
type)
dom = kzalloc(sizeof(*dom), GFP_KERNEL);
if (!dom)
return NULL;
+   mutex_init(>mutex);
 
return >domain;
 }
@@ -455,14 +458,19 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
if (domid < 0)
return domid;
 
+   mutex_lock(>mutex);
if (!dom->data) {
/* Data is in the frstdata in sharing pgtable case. */
frstdata = mtk_iommu_get_m4u_data();
 
-   if (mtk_iommu_domain_finalise(dom, frstdata, domid))
+   ret = mtk_iommu_domain_finalise(dom, frstdata, domid);
+   if (ret) {
+   mutex_unlock(>mutex);
return -ENODEV;
+   }
dom->data = data;
}
+   mutex_unlock(>mutex);
 
mutex_lock(>mutex);
if (!data->m4u_dom) { /* Initialize the M4U HW */
-- 
2.18.0

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


[PATCH v4 06/35] iommu/mediatek: Add mutex for m4u_group and m4u_dom in data

2022-01-25 Thread Yong Wu
Add a mutex to protect the data in the structure mtk_iommu_data,
like ->"m4u_group" ->"m4u_dom". For the internal data, we should
protect it in ourselves driver. Add a mutex for this.
This could be a fix for the multi-groups support.

Fixes: c3045f39244e ("iommu/mediatek: Support for multi domains")
Signed-off-by: Yunfei Wang 
Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 13 +++--
 drivers/iommu/mtk_iommu.h |  2 ++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index ec2c387abf60..095736bfb7b4 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -464,15 +464,16 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
dom->data = data;
}
 
+   mutex_lock(>mutex);
if (!data->m4u_dom) { /* Initialize the M4U HW */
ret = pm_runtime_resume_and_get(m4udev);
if (ret < 0)
-   return ret;
+   goto data_unlock;
 
ret = mtk_iommu_hw_init(data);
if (ret) {
pm_runtime_put(m4udev);
-   return ret;
+   goto data_unlock;
}
data->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
@@ -480,9 +481,14 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
 
pm_runtime_put(m4udev);
}
+   mutex_unlock(>mutex);
 
mtk_iommu_config(data, dev, true, domid);
return 0;
+
+data_unlock:
+   mutex_unlock(>mutex);
+   return ret;
 }
 
 static void mtk_iommu_detach_device(struct iommu_domain *domain,
@@ -592,6 +598,7 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
if (domid < 0)
return ERR_PTR(domid);
 
+   mutex_lock(>mutex);
group = data->m4u_group[domid];
if (!group) {
group = iommu_group_alloc();
@@ -600,6 +607,7 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
} else {
iommu_group_ref_get(group);
}
+   mutex_unlock(>mutex);
return group;
 }
 
@@ -874,6 +882,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
}
 
platform_set_drvdata(pdev, data);
+   mutex_init(>mutex);
 
ret = iommu_device_sysfs_add(>iommu, dev, NULL,
 "mtk-iommu.%pa", );
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index f81fa8862ed0..f413546ac6e5 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -80,6 +80,8 @@ struct mtk_iommu_data {
 
struct dma_iommu_mapping*mapping; /* For mtk_iommu_v1.c */
 
+   struct mutexmutex; /* Protect m4u_group/m4u_dom 
above */
+
struct list_headlist;
struct mtk_smi_larb_iommu   larb_imu[MTK_LARB_NR_MAX];
 };
-- 
2.18.0

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


[PATCH v4 05/35] iommu/mediatek: Remove clk_disable in mtk_iommu_remove

2022-01-25 Thread Yong Wu
After the commit b34ea31fe013 ("iommu/mediatek: Always enable the clk on
resume"), the iommu clock is controlled by the runtime callback.
thus remove the clk control in the mtk_iommu_remove.

Otherwise, it will warning like:

echo 14018000.iommu > /sys/bus/platform/drivers/mtk-iommu/unbind

[   51.413044] [ cut here ]
[   51.413648] vpp0_smi_iommu already disabled
[   51.414233] WARNING: CPU: 2 PID: 157 at */v5.15-rc1/kernel/mediatek/
  drivers/clk/clk.c:952 clk_core_disable+0xb0/0xb8
[   51.417174] Hardware name: MT8195V/C(ENG) (DT)
[   51.418635] pc : clk_core_disable+0xb0/0xb8
[   51.419177] lr : clk_core_disable+0xb0/0xb8
...
[   51.429375] Call trace:
[   51.429694]  clk_core_disable+0xb0/0xb8
[   51.430193]  clk_core_disable_lock+0x24/0x40
[   51.430745]  clk_disable+0x20/0x30
[   51.431189]  mtk_iommu_remove+0x58/0x118
[   51.431705]  platform_remove+0x28/0x60
[   51.432197]  device_release_driver_internal+0x110/0x1f0
[   51.432873]  device_driver_detach+0x18/0x28
[   51.433418]  unbind_store+0xd4/0x108
[   51.433886]  drv_attr_store+0x24/0x38
[   51.434363]  sysfs_kf_write+0x40/0x58
[   51.434843]  kernfs_fop_write_iter+0x164/0x1e0

Fixes: b34ea31fe013 ("iommu/mediatek: Always enable the clk on resume")
Reported-by: Hsin-Yi Wang 
Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 6ccfd7bac9df..ec2c387abf60 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -921,7 +921,6 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 
list_del(>list);
 
-   clk_disable_unprepare(data->bclk);
device_link_remove(data->smicomm_dev, >dev);
pm_runtime_disable(>dev);
devm_free_irq(>dev, data->irq, data);
-- 
2.18.0

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


[PATCH v4 04/35] iommu/mediatek: Add list_del in mtk_iommu_remove

2022-01-25 Thread Yong Wu
Lack the list_del in the mtk_iommu_remove, and remove
bus_set_iommu(*, NULL) since there may be several iommu HWs.
we can not bus_set_iommu null when one iommu driver unbind.

This could be a fix for mt2712 which support 2 M4U HW and list them.

Fixes: 7c3a2ec02806 ("iommu/mediatek: Merge 2 M4U HWs into one iommu domain")
Signed-off-by: Yong Wu 
Reviewed-by: AngeloGioacchino Del Regno 

---
 drivers/iommu/mtk_iommu.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index a92b01805232..6ccfd7bac9df 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -919,8 +919,7 @@ static int mtk_iommu_remove(struct platform_device *pdev)
iommu_device_sysfs_remove(>iommu);
iommu_device_unregister(>iommu);
 
-   if (iommu_present(_bus_type))
-   bus_set_iommu(_bus_type, NULL);
+   list_del(>list);
 
clk_disable_unprepare(data->bclk);
device_link_remove(data->smicomm_dev, >dev);
-- 
2.18.0

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


[PATCH v4 03/35] iommu/mediatek: Fix 2 HW sharing pgtable issue

2022-01-25 Thread Yong Wu
In the commit 4f956c97d26b ("iommu/mediatek: Move domain_finalise into
attach_device"), I overlooked the sharing pgtable case.
After that commit, the "data" in the mtk_iommu_domain_finalise always is
the data of the current IOMMU HW. Fix this for the sharing pgtable case.

Only affect mt2712 which is the only SoC that share pgtable currently.

Fixes: 4f956c97d26b ("iommu/mediatek: Move domain_finalise into attach_device")
Signed-off-by: Yong Wu 
---
 drivers/iommu/mtk_iommu.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index eb43e7edb9dc..a92b01805232 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -446,7 +446,7 @@ static void mtk_iommu_domain_free(struct iommu_domain 
*domain)
 static int mtk_iommu_attach_device(struct iommu_domain *domain,
   struct device *dev)
 {
-   struct mtk_iommu_data *data = dev_iommu_priv_get(dev);
+   struct mtk_iommu_data *data = dev_iommu_priv_get(dev), *frstdata;
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
struct device *m4udev = data->dev;
int ret, domid;
@@ -456,7 +456,10 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
return domid;
 
if (!dom->data) {
-   if (mtk_iommu_domain_finalise(dom, data, domid))
+   /* Data is in the frstdata in sharing pgtable case. */
+   frstdata = mtk_iommu_get_m4u_data();
+
+   if (mtk_iommu_domain_finalise(dom, frstdata, domid))
return -ENODEV;
dom->data = data;
}
-- 
2.18.0

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


[PATCH v4 02/35] dt-bindings: mediatek: mt8195: Add binding for infra IOMMU

2022-01-25 Thread Yong Wu
In mt8195, we have a new IOMMU that is for INFRA IOMMU. its masters
mainly are PCIe and USB. Different with MM IOMMU, all these masters
connect with IOMMU directly, there is no mediatek,larbs property for
infra IOMMU.

Another thing is about PCIe ports. currently the function
"of_iommu_configure_dev_id" only support the id number is 1, But our
PCIe have two ports, one is for reading and the other is for writing.
see more about the PCIe patch in this patchset. Thus, I only list
the reading id here and add the other id in our driver.

Signed-off-by: Yong Wu 
Acked-by: Krzysztof Kozlowski 
Reviewed-by: Rob Herring 
---
 .../bindings/iommu/mediatek,iommu.yaml | 13 -
 .../dt-bindings/memory/mt8195-memory-port.h| 18 ++
 include/dt-bindings/memory/mtk-memory-port.h   |  2 ++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml 
b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index 9b04630158c8..c528a299afa9 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -79,6 +79,7 @@ properties:
   - mediatek,mt8192-m4u  # generation two
   - mediatek,mt8195-iommu-vdo# generation two
   - mediatek,mt8195-iommu-vpp# generation two
+  - mediatek,mt8195-iommu-infra  # generation two
 
   - description: mt7623 generation one
 items:
@@ -129,7 +130,6 @@ required:
   - compatible
   - reg
   - interrupts
-  - mediatek,larbs
   - '#iommu-cells'
 
 allOf:
@@ -161,6 +161,17 @@ allOf:
   required:
 - power-domains
 
+  - if: # The IOMMUs don't have larbs.
+  not:
+properties:
+  compatible:
+contains:
+  const: mediatek,mt8195-iommu-infra
+
+then:
+  required:
+- mediatek,larbs
+
 additionalProperties: false
 
 examples:
diff --git a/include/dt-bindings/memory/mt8195-memory-port.h 
b/include/dt-bindings/memory/mt8195-memory-port.h
index eeafad451a1d..fe948fec0688 100644
--- a/include/dt-bindings/memory/mt8195-memory-port.h
+++ b/include/dt-bindings/memory/mt8195-memory-port.h
@@ -387,4 +387,22 @@
 #define M4U_PORT_L28_CAM_DRZS4NO_R1MTK_M4U_ID(28, 5)
 #define M4U_PORT_L28_CAM_TNCSO_R1  MTK_M4U_ID(28, 6)
 
+/* Infra iommu ports */
+/* PCIe1: read: BIT16; write BIT17. */
+#define IOMMU_PORT_INFRA_PCIE1 MTK_IFAIOMMU_PERI_ID(16)
+/* PCIe0: read: BIT18; write BIT19. */
+#define IOMMU_PORT_INFRA_PCIE0 MTK_IFAIOMMU_PERI_ID(18)
+#define IOMMU_PORT_INFRA_SSUSB_P3_RMTK_IFAIOMMU_PERI_ID(20)
+#define IOMMU_PORT_INFRA_SSUSB_P3_WMTK_IFAIOMMU_PERI_ID(21)
+#define IOMMU_PORT_INFRA_SSUSB_P2_RMTK_IFAIOMMU_PERI_ID(22)
+#define IOMMU_PORT_INFRA_SSUSB_P2_WMTK_IFAIOMMU_PERI_ID(23)
+#define IOMMU_PORT_INFRA_SSUSB_P1_1_R  MTK_IFAIOMMU_PERI_ID(24)
+#define IOMMU_PORT_INFRA_SSUSB_P1_1_W  MTK_IFAIOMMU_PERI_ID(25)
+#define IOMMU_PORT_INFRA_SSUSB_P1_0_R  MTK_IFAIOMMU_PERI_ID(26)
+#define IOMMU_PORT_INFRA_SSUSB_P1_0_W  MTK_IFAIOMMU_PERI_ID(27)
+#define IOMMU_PORT_INFRA_SSUSB2_R  MTK_IFAIOMMU_PERI_ID(28)
+#define IOMMU_PORT_INFRA_SSUSB2_W  MTK_IFAIOMMU_PERI_ID(29)
+#define IOMMU_PORT_INFRA_SSUSB_R   MTK_IFAIOMMU_PERI_ID(30)
+#define IOMMU_PORT_INFRA_SSUSB_W   MTK_IFAIOMMU_PERI_ID(31)
+
 #endif
diff --git a/include/dt-bindings/memory/mtk-memory-port.h 
b/include/dt-bindings/memory/mtk-memory-port.h
index 7d64103209af..2f68a0511a25 100644
--- a/include/dt-bindings/memory/mtk-memory-port.h
+++ b/include/dt-bindings/memory/mtk-memory-port.h
@@ -12,4 +12,6 @@
 #define MTK_M4U_TO_LARB(id)(((id) >> 5) & 0x1f)
 #define MTK_M4U_TO_PORT(id)((id) & 0x1f)
 
+#define MTK_IFAIOMMU_PERI_ID(port) MTK_M4U_ID(0, port)
+
 #endif
-- 
2.18.0

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


[PATCH v4 01/35] dt-bindings: mediatek: mt8195: Add binding for MM IOMMU

2022-01-25 Thread Yong Wu
This patch adds descriptions for mt8195 IOMMU which also use ARM
Short-Descriptor translation table format.

In mt8195, there are two smi-common HW and IOMMU, one is for vdo(video
output), the other is for vpp(video processing pipe). They connects
with different smi-larbs, then some setting(larbid_remap) is different.
Differentiate them with the compatible string.

Something like this:

IOMMU(VDO)  IOMMU(VPP)
   |   |
  SMI_COMMON_VDO  SMI_COMMON_VPP
  --- 
  |  |   ...  |  | ...
larb0 larb2  ...larb1 larb3...

Another change is that we have a new IOMMU that is for infra master like
PCIe and USB. The infra master don't have the larb and ports, thus we
rename the port header file to mt8195-memory-port.h rather than
mt8195-larb-port.h.

Also, the IOMMU is not only for MM, thus, we don't call it "m4u" which
means "MultiMedia Memory Management UNIT". thus, use the "iommu" as the
compatiable string.

Signed-off-by: Yong Wu 
Acked-by: Krzysztof Kozlowski 
Reviewed-by: Rob Herring 
---
 .../bindings/iommu/mediatek,iommu.yaml|   7 +
 .../dt-bindings/memory/mt8195-memory-port.h   | 390 ++
 2 files changed, 397 insertions(+)
 create mode 100644 include/dt-bindings/memory/mt8195-memory-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml 
b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
index 0f26fe14c8e2..9b04630158c8 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml
@@ -77,6 +77,8 @@ properties:
   - mediatek,mt8173-m4u  # generation two
   - mediatek,mt8183-m4u  # generation two
   - mediatek,mt8192-m4u  # generation two
+  - mediatek,mt8195-iommu-vdo# generation two
+  - mediatek,mt8195-iommu-vpp# generation two
 
   - description: mt7623 generation one
 items:
@@ -118,6 +120,7 @@ properties:
   dt-binding/memory/mt8173-larb-port.h for mt8173,
   dt-binding/memory/mt8183-larb-port.h for mt8183,
   dt-binding/memory/mt8192-larb-port.h for mt8192.
+  dt-binding/memory/mt8195-memory-port.h for mt8195.
 
   power-domains:
 maxItems: 1
@@ -139,6 +142,8 @@ allOf:
   - mediatek,mt2712-m4u
   - mediatek,mt8173-m4u
   - mediatek,mt8192-m4u
+  - mediatek,mt8195-iommu-vdo
+  - mediatek,mt8195-iommu-vpp
 
 then:
   required:
@@ -149,6 +154,8 @@ allOf:
 compatible:
   enum:
 - mediatek,mt8192-m4u
+- mediatek,mt8195-iommu-vdo
+- mediatek,mt8195-iommu-vpp
 
 then:
   required:
diff --git a/include/dt-bindings/memory/mt8195-memory-port.h 
b/include/dt-bindings/memory/mt8195-memory-port.h
new file mode 100644
index ..eeafad451a1d
--- /dev/null
+++ b/include/dt-bindings/memory/mt8195-memory-port.h
@@ -0,0 +1,390 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Yong Wu 
+ */
+#ifndef _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_
+#define _DT_BINDINGS_MEMORY_MT8195_LARB_PORT_H_
+
+#include 
+
+/*
+ * MM IOMMU supports 16GB dma address. We separate it to four ranges:
+ * 0 ~ 4G; 4G ~ 8G; 8G ~ 12G; 12G ~ 16G, we could adjust these masters
+ * locate in anyone bank. BUT:
+ * a) Make sure all the ports inside a larb are in one range.
+ * b) The iova of any master can NOT cross the 4G/8G/12G boundary.
+ *
+ * This is the suggested mapping in this SoC:
+ *
+ * modulesdma-address-region   larbs-ports
+ * disp 0 ~ 4G  larb0/1/2/3
+ * vcodec  4G ~ 8G  larb19/20/21/22/23/24
+ * cam/mdp 8G ~ 12G the other larbs.
+ * N/A 12G ~ 16G
+ * CCU0   0x24000_ ~ 0x243ff_   larb18: port 0/1
+ * CCU1   0x24400_ ~ 0x247ff_   larb18: port 2/3
+ *
+ * This SoC have two IOMMU HWs, this is the detailed connected information:
+ * iommu-vdo: larb0/2/5/7/9/10/11/13/17/19/21/24/25/28
+ * iommu-vpp: larb1/3/4/6/8/12/14/16/18/20/22/23/26/27
+ */
+
+/* MM IOMMU ports */
+/* larb0 */
+#define M4U_PORT_L0_DISP_RDMA0 MTK_M4U_ID(0, 0)
+#define M4U_PORT_L0_DISP_WDMA0 MTK_M4U_ID(0, 1)
+#define M4U_PORT_L0_DISP_OVL0_RDMA0MTK_M4U_ID(0, 2)
+#define M4U_PORT_L0_DISP_OVL0_RDMA1MTK_M4U_ID(0, 3)
+#define M4U_PORT_L0_DISP_OVL0_HDR  MTK_M4U_ID(0, 4)
+#define M4U_PORT_L0_DISP_FAKE0 MTK_M4U_ID(0, 5)
+
+/* larb1 */
+#define M4U_PORT_L1_DISP_RDMA0 MTK_M4U_ID(1, 0)
+#define M4U_PORT_L1_DISP_WDMA0 MTK_M4U_ID(1, 1)
+#define M4U_PORT_L1_DISP_OVL0_RDMA0MTK_M4U_ID(1, 2)
+#define M4U_PORT_L1_DISP_OVL0_RDMA1MTK_M4U_ID(1, 3)
+#define M4U_PORT_L1_DISP_OVL0_HDR  MTK_M4U_ID(1, 4)
+#define M4U_PORT_L1_DISP_FAKE0 MTK_M4U_ID(1, 5)

[PATCH v4 00/35] MT8195 IOMMU SUPPORT

2022-01-25 Thread Yong Wu
This patchset adds MT8195 iommu support.

MT8195 have 3 IOMMU HWs. 2 IOMMU HW is for multimedia, and 1 IOMMU HW is
for infra-master, like PCIe/USB.

About the 2 MM IOMMU HW, something like this:

IOMMU(VDO)  IOMMU(VPP)
   |   |
  SMI_COMMON(VDO)  SMI_COMMON(VPP)
  --- 
  |  |   ...  |  | ...
larb0 larb2  ...larb1 larb3...

these two MM IOMMU HW share a pgtable.

About the INFRA IOMMU, it don't have larbs, the master connects the iommu
directly. It use a independent pgtable.

Also, mt8195 IOMMU bank supports. Normally the IOMMU register size only
is 0x1000. In this IOMMU HW, the register size is 5 * 0x1000. each 0x1000
is a bank. the banks' register look like this:
 
 |bank0  | bank1 | bank2 | bank3 | bank4|
 
 |global |
 |control| null
 |regs   |
 -
 |bank   |bank   |bank   |bank   |bank   |
 |regs   |regs   |regs   |regs   |regs   |
 |   |   |   |   |   |
 -
All the banks share some global control registers, and each bank have its
special bank registers, like pgtable base register, tlb operation registers,
the fault status registers.
 
In mt8195, we enable this bank feature for infra iommu, We put PCIe in bank0
and USB in bank4. they have independent pgtable.

Change note:
v4:1) Base on v5.16-rc1
   2) Base on tlb logic 2, some patches in v3 has already gone through in that
   patchset.
   
https://lore.kernel.org/linux-mediatek/20211208120744.2415-1-dafna.hirschf...@collabora.com/
  
   3) Due to the unreadable union for v1/v2(comment in 26/33 of v3), I
   separate mtk_iommu_data for v1 and v2 totally, then remove mtk_iommu.h.
   please see patch[26/35][27/35].
   4) add two mutex for the internal data. patch[6/35][7/35].
   5) add a new flag PM_CLK_AO.

v3: 
https://lore.kernel.org/linux-mediatek/20210923115840.17813-1-yong...@mediatek.com/
1) base on v5.15-rc1
2) Adjust devlink with smi-common, not use the property(sub-sommon).
3) Adjust tlb_flush_all flow,
   a) Fix tlb_flush_all only is supported in bank0.
   b) add tlb-flush-all in the resume callback.
   c) remove the pm status checking in tlb-flush-all.
   The reason are showed in the commit message.
4) Allow IOMMU_DOMAIN_UNMANAGED since PCIe VFIO use that.
5) Fix a clk warning and a null abort when unbind the iommu driver.

v2: 
https://lore.kernel.org/linux-mediatek/20210813065324.29220-1-yong...@mediatek.com/
1) Base on v5.14-rc1.
2) Fix build fail for arm32.
3) Fix dt-binding issue from Rob.
4) Fix the bank issue when tlb flush. v1 always use bank->base.
5) adjust devlink with smi-common since the node may be smi-sub-common.
6) other changes: like reword some commit message(removing many
   "This patch..."); seperate serveral patches.

v1: 
https://lore.kernel.org/linux-mediatek/20210630023504.18177-1-yong...@mediatek.com/
Base on v5.13-rc1

Yong Wu (35):
  dt-bindings: mediatek: mt8195: Add binding for MM IOMMU
  dt-bindings: mediatek: mt8195: Add binding for infra IOMMU
  iommu/mediatek: Fix 2 HW sharing pgtable issue
  iommu/mediatek: Add list_del in mtk_iommu_remove
  iommu/mediatek: Remove clk_disable in mtk_iommu_remove
  iommu/mediatek: Add mutex for m4u_group and m4u_dom in data
  iommu/mediatek: Add mutex for data in the mtk_iommu_domain
  iommu/mediatek: Use kmalloc for protect buffer
  iommu/mediatek: Adapt sharing and non-sharing pgtable case
  iommu/mediatek: Add 12G~16G support for multi domains
  iommu/mediatek: Add a flag DCM_DISABLE
  iommu/mediatek: Add a flag NON_STD_AXI
  iommu/mediatek: Remove the granule in the tlb flush
  iommu/mediatek: Always enable output PA over 32bits in isr
  iommu/mediatek: Add SUB_COMMON_3BITS flag
  iommu/mediatek: Add IOMMU_TYPE flag
  iommu/mediatek: Contain MM IOMMU flow with the MM TYPE
  iommu/mediatek: Adjust device link when it is sub-common
  iommu/mediatek: Allow IOMMU_DOMAIN_UNMANAGED for PCIe VFIO
  iommu/mediatek: Add a PM_CLK_AO flag for infra iommu
  iommu/mediatek: Add infra iommu support
  iommu/mediatek: Add PCIe support
  iommu/mediatek: Add mt8195 support
  iommu/mediatek: Only adjust code about register base
  iommu/mediatek: Just move code position in hw_init
  iommu/mediatek: Separate mtk_iommu_data for v1 and v2
  iommu/mediatek: Remove mtk_iommu.h
  iommu/mediatek-v1: Just rename mtk_iommu to mtk_iommu_v1
  iommu/mediatek: Add mtk_iommu_bank_data structure
  iommu/mediatek: Initialise bank HW for each a bank
  iommu/mediatek: Change the domid to iova_region_id
  iommu/mediatek: Get the proper bankid for multi banks
  iommu/mediatek: Initialise/Remove for multi bank dev
  iommu/mediatek: Backup/restore regsiters for multi banks
  iommu/mediatek: mt8195: Enable