diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index b7de23c7d2..652e1712ec 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -655,6 +655,7 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu, goto out; } else { if (cache) { + /* valid->valid transitions reuse the DMA slot */ if (cache->perm == entry->perm && cache->translated_addr == entry->translated_addr) { goto out; @@ -665,6 +666,9 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu, memory_region_notify_iommu(&iommu->iommu_mr, 0, event); event.type = IOMMU_NOTIFIER_MAP; event.entry.perm = entry->perm; + } else { + /* invalid->valid transitions consume a new DMA slot */ + dec_dma_avail(iommu); } cache = g_new(S390IOTLBEntry, 1); @@ -673,7 +677,6 @@ static uint32_t s390_pci_update_iotlb(S390PCIIOMMU *iommu, cache->len = TARGET_PAGE_SIZE; cache->perm = entry->perm; g_hash_table_replace(iommu->iotlb, &cache->iova, cache); - dec_dma_avail(iommu); } /*