+++ /dev/null
-From a1b204341623ffd65190d4e1443a7c5710d2ade2 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 13 Sep 2023 10:43:37 -0300
-Subject: iommu: Add IOMMU_DOMAIN_PLATFORM for S390
-
-From: Jason Gunthorpe <jgg@nvidia.com>
-
-[ Upstream commit e04c7487a6655722172e93e8f36e51d6ab279f86 ]
-
-The PLATFORM domain will be set as the default domain and attached as
-normal during probe. The driver will ignore the initial attach from a NULL
-domain to the PLATFORM domain.
-
-After this, the PLATFORM domain's attach_dev will be called whenever we
-detach from an UNMANAGED domain (eg for VFIO). This is the same time the
-original design would have called op->detach_dev().
-
-This is temporary until the S390 dma-iommu.c conversion is merged.
-
-Tested-by: Heiko Stuebner <heiko@sntech.de>
-Tested-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
-Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
-Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
-Link: https://lore.kernel.org/r/4-v8-81230027b2fa+9d-iommu_all_defdom_jgg@nvidia.com
-Signed-off-by: Joerg Roedel <jroedel@suse.de>
-Stable-dep-of: 45537926dd2a ("s390/pci: Fix stale function handles in error handling")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/iommu/s390-iommu.c | 21 +++++++++++++++++++--
- 1 file changed, 19 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
-index fbf59a8db29b1..f0c867c57a5b9 100644
---- a/drivers/iommu/s390-iommu.c
-+++ b/drivers/iommu/s390-iommu.c
-@@ -142,14 +142,31 @@ static int s390_iommu_attach_device(struct iommu_domain *domain,
- return 0;
- }
-
--static void s390_iommu_set_platform_dma(struct device *dev)
-+/*
-+ * Switch control over the IOMMU to S390's internal dma_api ops
-+ */
-+static int s390_iommu_platform_attach(struct iommu_domain *platform_domain,
-+ struct device *dev)
- {
- struct zpci_dev *zdev = to_zpci_dev(dev);
-
-+ if (!zdev->s390_domain)
-+ return 0;
-+
- __s390_iommu_detach_device(zdev);
- zpci_dma_init_device(zdev);
-+ return 0;
- }
-
-+static struct iommu_domain_ops s390_iommu_platform_ops = {
-+ .attach_dev = s390_iommu_platform_attach,
-+};
-+
-+static struct iommu_domain s390_iommu_platform_domain = {
-+ .type = IOMMU_DOMAIN_PLATFORM,
-+ .ops = &s390_iommu_platform_ops,
-+};
-+
- static void s390_iommu_get_resv_regions(struct device *dev,
- struct list_head *list)
- {
-@@ -428,12 +445,12 @@ void zpci_destroy_iommu(struct zpci_dev *zdev)
- }
-
- static const struct iommu_ops s390_iommu_ops = {
-+ .default_domain = &s390_iommu_platform_domain,
- .capable = s390_iommu_capable,
- .domain_alloc = s390_domain_alloc,
- .probe_device = s390_iommu_probe_device,
- .release_device = s390_iommu_release_device,
- .device_group = generic_device_group,
-- .set_platform_dma_ops = s390_iommu_set_platform_dma,
- .pgsize_bitmap = SZ_4K,
- .get_resv_regions = s390_iommu_get_resv_regions,
- .default_domain_ops = &(const struct iommu_domain_ops) {
---
-2.39.5
-
+++ /dev/null
-From f9311abe76e26880f417b581cefba8366abcc893 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 28 Sep 2023 16:31:35 +0200
-Subject: iommu: Allow .iotlb_sync_map to fail and handle s390's -ENOMEM return
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit fa4c4507099f781ca89a748c480af9cf97629726 ]
-
-On s390 when using a paging hypervisor, .iotlb_sync_map is used to sync
-mappings by letting the hypervisor inspect the synced IOVA range and
-updating a shadow table. This however means that .iotlb_sync_map can
-fail as the hypervisor may run out of resources while doing the sync.
-This can be due to the hypervisor being unable to pin guest pages, due
-to a limit on mapped addresses such as vfio_iommu_type1.dma_entry_limit
-or lack of other resources. Either way such a failure to sync a mapping
-should result in a DMA_MAPPING_ERROR.
-
-Now especially when running with batched IOTLB flushes for unmap it may
-be that some IOVAs have already been invalidated but not yet synced via
-.iotlb_sync_map. Thus if the hypervisor indicates running out of
-resources, first do a global flush allowing the hypervisor to free
-resources associated with these mappings as well a retry creating the
-new mappings and only if that also fails report this error to callers.
-
-Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
-Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
-Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com> # sun50i
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Link: https://lore.kernel.org/r/20230928-dma_iommu-v13-1-9e5fc4dacc36@linux.ibm.com
-Signed-off-by: Joerg Roedel <jroedel@suse.de>
-Stable-dep-of: 45537926dd2a ("s390/pci: Fix stale function handles in error handling")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/iommu/amd/iommu.c | 5 +++--
- drivers/iommu/apple-dart.c | 5 +++--
- drivers/iommu/intel/iommu.c | 5 +++--
- drivers/iommu/iommu.c | 20 ++++++++++++++++----
- drivers/iommu/msm_iommu.c | 5 +++--
- drivers/iommu/mtk_iommu.c | 5 +++--
- drivers/iommu/s390-iommu.c | 29 +++++++++++++++++++++++------
- drivers/iommu/sprd-iommu.c | 5 +++--
- drivers/iommu/sun50i-iommu.c | 6 ++++--
- include/linux/iommu.h | 4 ++--
- 10 files changed, 63 insertions(+), 26 deletions(-)
-
-diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
-index a5d6d786dba52..d6344b74d873c 100644
---- a/drivers/iommu/amd/iommu.c
-+++ b/drivers/iommu/amd/iommu.c
-@@ -2241,14 +2241,15 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
- return ret;
- }
-
--static void amd_iommu_iotlb_sync_map(struct iommu_domain *dom,
-- unsigned long iova, size_t size)
-+static int amd_iommu_iotlb_sync_map(struct iommu_domain *dom,
-+ unsigned long iova, size_t size)
- {
- struct protection_domain *domain = to_pdomain(dom);
- struct io_pgtable_ops *ops = &domain->iop.iop.ops;
-
- if (ops->map_pages)
- domain_flush_np_cache(domain, iova, size);
-+ return 0;
- }
-
- static int amd_iommu_map_pages(struct iommu_domain *dom, unsigned long iova,
-diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
-index 0b89275084274..d6263ce05b9ba 100644
---- a/drivers/iommu/apple-dart.c
-+++ b/drivers/iommu/apple-dart.c
-@@ -506,10 +506,11 @@ static void apple_dart_iotlb_sync(struct iommu_domain *domain,
- apple_dart_domain_flush_tlb(to_dart_domain(domain));
- }
-
--static void apple_dart_iotlb_sync_map(struct iommu_domain *domain,
-- unsigned long iova, size_t size)
-+static int apple_dart_iotlb_sync_map(struct iommu_domain *domain,
-+ unsigned long iova, size_t size)
- {
- apple_dart_domain_flush_tlb(to_dart_domain(domain));
-+ return 0;
- }
-
- static phys_addr_t apple_dart_iova_to_phys(struct iommu_domain *domain,
-diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
-index 6a745616d85a4..ddfde6edf7566 100644
---- a/drivers/iommu/intel/iommu.c
-+++ b/drivers/iommu/intel/iommu.c
-@@ -4680,8 +4680,8 @@ static bool risky_device(struct pci_dev *pdev)
- return false;
- }
-
--static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
-- unsigned long iova, size_t size)
-+static int intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
-+ unsigned long iova, size_t size)
- {
- struct dmar_domain *dmar_domain = to_dmar_domain(domain);
- unsigned long pages = aligned_nrpages(iova, size);
-@@ -4691,6 +4691,7 @@ static void intel_iommu_iotlb_sync_map(struct iommu_domain *domain,
-
- xa_for_each(&dmar_domain->iommu_array, i, info)
- __mapping_notify_one(info->iommu, dmar_domain, pfn, pages);
-+ return 0;
- }
-
- static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
-diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
-index 3fa5699b9ff19..481eb6766ee13 100644
---- a/drivers/iommu/iommu.c
-+++ b/drivers/iommu/iommu.c
-@@ -2530,8 +2530,17 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova,
- return -EINVAL;
-
- ret = __iommu_map(domain, iova, paddr, size, prot, gfp);
-- if (ret == 0 && ops->iotlb_sync_map)
-- ops->iotlb_sync_map(domain, iova, size);
-+ if (ret == 0 && ops->iotlb_sync_map) {
-+ ret = ops->iotlb_sync_map(domain, iova, size);
-+ if (ret)
-+ goto out_err;
-+ }
-+
-+ return ret;
-+
-+out_err:
-+ /* undo mappings already done */
-+ iommu_unmap(domain, iova, size);
-
- return ret;
- }
-@@ -2672,8 +2681,11 @@ ssize_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
- sg = sg_next(sg);
- }
-
-- if (ops->iotlb_sync_map)
-- ops->iotlb_sync_map(domain, iova, mapped);
-+ if (ops->iotlb_sync_map) {
-+ ret = ops->iotlb_sync_map(domain, iova, mapped);
-+ if (ret)
-+ goto out_err;
-+ }
- return mapped;
-
- out_err:
-diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
-index 79d89bad5132b..47926d3290e6c 100644
---- a/drivers/iommu/msm_iommu.c
-+++ b/drivers/iommu/msm_iommu.c
-@@ -486,12 +486,13 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova,
- return ret;
- }
-
--static void msm_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
-- size_t size)
-+static int msm_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
-+ size_t size)
- {
- struct msm_priv *priv = to_msm_priv(domain);
-
- __flush_iotlb_range(iova, size, SZ_4K, false, priv);
-+ return 0;
- }
-
- static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
-diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
-index 06c0770ff894e..2cba98233be0f 100644
---- a/drivers/iommu/mtk_iommu.c
-+++ b/drivers/iommu/mtk_iommu.c
-@@ -817,12 +817,13 @@ static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
- mtk_iommu_tlb_flush_range_sync(gather->start, length, dom->bank);
- }
-
--static void mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
-- size_t size)
-+static int mtk_iommu_sync_map(struct iommu_domain *domain, unsigned long iova,
-+ size_t size)
- {
- struct mtk_iommu_domain *dom = to_mtk_domain(domain);
-
- mtk_iommu_tlb_flush_range_sync(iova, size, dom->bank);
-+ return 0;
- }
-
- static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
-diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
-index f0c867c57a5b9..3b512e52610b1 100644
---- a/drivers/iommu/s390-iommu.c
-+++ b/drivers/iommu/s390-iommu.c
-@@ -222,6 +222,12 @@ static void s390_iommu_release_device(struct device *dev)
- __s390_iommu_detach_device(zdev);
- }
-
-+static int zpci_refresh_all(struct zpci_dev *zdev)
-+{
-+ return zpci_refresh_trans((u64)zdev->fh << 32, zdev->start_dma,
-+ zdev->end_dma - zdev->start_dma + 1);
-+}
-+
- static void s390_iommu_flush_iotlb_all(struct iommu_domain *domain)
- {
- struct s390_domain *s390_domain = to_s390_domain(domain);
-@@ -229,8 +235,7 @@ static void s390_iommu_flush_iotlb_all(struct iommu_domain *domain)
-
- rcu_read_lock();
- list_for_each_entry_rcu(zdev, &s390_domain->devices, iommu_list) {
-- zpci_refresh_trans((u64)zdev->fh << 32, zdev->start_dma,
-- zdev->end_dma - zdev->start_dma + 1);
-+ zpci_refresh_all(zdev);
- }
- rcu_read_unlock();
- }
-@@ -254,20 +259,32 @@ static void s390_iommu_iotlb_sync(struct iommu_domain *domain,
- rcu_read_unlock();
- }
-
--static void s390_iommu_iotlb_sync_map(struct iommu_domain *domain,
-- unsigned long iova, size_t size)
-+static int s390_iommu_iotlb_sync_map(struct iommu_domain *domain,
-+ unsigned long iova, size_t size)
- {
- struct s390_domain *s390_domain = to_s390_domain(domain);
- struct zpci_dev *zdev;
-+ int ret = 0;
-
- rcu_read_lock();
- list_for_each_entry_rcu(zdev, &s390_domain->devices, iommu_list) {
- if (!zdev->tlb_refresh)
- continue;
-- zpci_refresh_trans((u64)zdev->fh << 32,
-- iova, size);
-+ ret = zpci_refresh_trans((u64)zdev->fh << 32,
-+ iova, size);
-+ /*
-+ * let the hypervisor discover invalidated entries
-+ * allowing it to free IOVAs and unpin pages
-+ */
-+ if (ret == -ENOMEM) {
-+ ret = zpci_refresh_all(zdev);
-+ if (ret)
-+ break;
-+ }
- }
- rcu_read_unlock();
-+
-+ return ret;
- }
-
- static int s390_iommu_validate_trans(struct s390_domain *s390_domain,
-diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
-index c8e79a2d8b4c6..03aea6ed0d422 100644
---- a/drivers/iommu/sprd-iommu.c
-+++ b/drivers/iommu/sprd-iommu.c
-@@ -345,8 +345,8 @@ static size_t sprd_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
- return size;
- }
-
--static void sprd_iommu_sync_map(struct iommu_domain *domain,
-- unsigned long iova, size_t size)
-+static int sprd_iommu_sync_map(struct iommu_domain *domain,
-+ unsigned long iova, size_t size)
- {
- struct sprd_iommu_domain *dom = to_sprd_domain(domain);
- unsigned int reg;
-@@ -358,6 +358,7 @@ static void sprd_iommu_sync_map(struct iommu_domain *domain,
-
- /* clear IOMMU TLB buffer after page table updated */
- sprd_iommu_write(dom->sdev, reg, 0xffffffff);
-+ return 0;
- }
-
- static void sprd_iommu_sync(struct iommu_domain *domain,
-diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
-index 94bd7f25f6f26..e6b2fe3db4216 100644
---- a/drivers/iommu/sun50i-iommu.c
-+++ b/drivers/iommu/sun50i-iommu.c
-@@ -402,8 +402,8 @@ static void sun50i_iommu_flush_iotlb_all(struct iommu_domain *domain)
- spin_unlock_irqrestore(&iommu->iommu_lock, flags);
- }
-
--static void sun50i_iommu_iotlb_sync_map(struct iommu_domain *domain,
-- unsigned long iova, size_t size)
-+static int sun50i_iommu_iotlb_sync_map(struct iommu_domain *domain,
-+ unsigned long iova, size_t size)
- {
- struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
- struct sun50i_iommu *iommu = sun50i_domain->iommu;
-@@ -412,6 +412,8 @@ static void sun50i_iommu_iotlb_sync_map(struct iommu_domain *domain,
- spin_lock_irqsave(&iommu->iommu_lock, flags);
- sun50i_iommu_zap_range(iommu, iova, size);
- spin_unlock_irqrestore(&iommu->iommu_lock, flags);
-+
-+ return 0;
- }
-
- static void sun50i_iommu_iotlb_sync(struct iommu_domain *domain,
-diff --git a/include/linux/iommu.h b/include/linux/iommu.h
-index b6ef263e85c06..187528e0ebb99 100644
---- a/include/linux/iommu.h
-+++ b/include/linux/iommu.h
-@@ -346,8 +346,8 @@ struct iommu_domain_ops {
- struct iommu_iotlb_gather *iotlb_gather);
-
- void (*flush_iotlb_all)(struct iommu_domain *domain);
-- void (*iotlb_sync_map)(struct iommu_domain *domain, unsigned long iova,
-- size_t size);
-+ int (*iotlb_sync_map)(struct iommu_domain *domain, unsigned long iova,
-+ size_t size);
- void (*iotlb_sync)(struct iommu_domain *domain,
- struct iommu_iotlb_gather *iotlb_gather);
-
---
-2.39.5
-
+++ /dev/null
-From 007b42e38c88f07284a4c275adbe54fc48a27803 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 25 Jun 2025 11:28:28 +0200
-Subject: s390/pci: Fix stale function handles in error handling
-
-From: Niklas Schnelle <schnelle@linux.ibm.com>
-
-[ Upstream commit 45537926dd2aaa9190ac0fac5a0fbeefcadfea95 ]
-
-The error event information for PCI error events contains a function
-handle for the respective function. This handle is generally captured at
-the time the error event was recorded. Due to delays in processing or
-cascading issues, it may happen that during firmware recovery multiple
-events are generated. When processing these events in order Linux may
-already have recovered an affected function making the event information
-stale. Fix this by doing an unconditional CLP List PCI function
-retrieving the current function handle with the zdev->state_lock held
-and ignoring the event if its function handle is stale.
-
-Cc: stable@vger.kernel.org
-Fixes: 4cdf2f4e24ff ("s390/pci: implement minimal PCI error recovery")
-Reviewed-by: Julian Ruess <julianr@linux.ibm.com>
-Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com>
-Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
-Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
-Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/s390/pci/pci_event.c | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
-index d969f36bf186f..fd83588f3c11d 100644
---- a/arch/s390/pci/pci_event.c
-+++ b/arch/s390/pci/pci_event.c
-@@ -257,6 +257,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
- struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
- struct pci_dev *pdev = NULL;
- pci_ers_result_t ers_res;
-+ u32 fh = 0;
-+ int rc;
-
- zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n",
- ccdf->fid, ccdf->fh, ccdf->pec);
-@@ -264,6 +266,16 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
- zpci_err_hex(ccdf, sizeof(*ccdf));
-
- if (zdev) {
-+ mutex_lock(&zdev->state_lock);
-+ rc = clp_refresh_fh(zdev->fid, &fh);
-+ if (rc)
-+ goto no_pdev;
-+ if (!fh || ccdf->fh != fh) {
-+ /* Ignore events with stale handles */
-+ zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n",
-+ ccdf->fid, fh, ccdf->fh);
-+ goto no_pdev;
-+ }
- zpci_update_fh(zdev, ccdf->fh);
- if (zdev->zbus->bus)
- pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
-@@ -292,6 +304,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf)
- }
- pci_dev_put(pdev);
- no_pdev:
-+ if (zdev)
-+ mutex_unlock(&zdev->state_lock);
- zpci_zdev_put(zdev);
- }
-
---
-2.39.5
-