s390/pci: handle insufficient resources during dma tlb flush
In a virtualized setup lazy flushing can lead to the hypervisor running out of resources when lots of guest pages need to be pinned. In this situation simply trigger a global flush to give the hypervisor a chance to free some of these resources. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
d39a01eff9
commit
a5f1005517
|
@ -181,6 +181,9 @@ out_unlock:
|
||||||
static int __dma_purge_tlb(struct zpci_dev *zdev, dma_addr_t dma_addr,
|
static int __dma_purge_tlb(struct zpci_dev *zdev, dma_addr_t dma_addr,
|
||||||
size_t size, int flags)
|
size_t size, int flags)
|
||||||
{
|
{
|
||||||
|
unsigned long irqflags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With zdev->tlb_refresh == 0, rpcit is not required to establish new
|
* With zdev->tlb_refresh == 0, rpcit is not required to establish new
|
||||||
* translations when previously invalid translation-table entries are
|
* translations when previously invalid translation-table entries are
|
||||||
|
@ -196,8 +199,22 @@ static int __dma_purge_tlb(struct zpci_dev *zdev, dma_addr_t dma_addr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return zpci_refresh_trans((u64) zdev->fh << 32, dma_addr,
|
ret = zpci_refresh_trans((u64) zdev->fh << 32, dma_addr,
|
||||||
PAGE_ALIGN(size));
|
PAGE_ALIGN(size));
|
||||||
|
if (ret == -ENOMEM && !s390_iommu_strict) {
|
||||||
|
/* enable the hypervisor to free some resources */
|
||||||
|
if (zpci_refresh_global(zdev))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&zdev->iommu_bitmap_lock, irqflags);
|
||||||
|
bitmap_andnot(zdev->iommu_bitmap, zdev->iommu_bitmap,
|
||||||
|
zdev->lazy_bitmap, zdev->iommu_pages);
|
||||||
|
bitmap_zero(zdev->lazy_bitmap, zdev->iommu_pages);
|
||||||
|
spin_unlock_irqrestore(&zdev->iommu_bitmap_lock, irqflags);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
|
static int dma_update_trans(struct zpci_dev *zdev, unsigned long pa,
|
||||||
|
|
|
@ -89,6 +89,9 @@ int zpci_refresh_trans(u64 fn, u64 addr, u64 range)
|
||||||
if (cc)
|
if (cc)
|
||||||
zpci_err_insn(cc, status, addr, range);
|
zpci_err_insn(cc, status, addr, range);
|
||||||
|
|
||||||
|
if (cc == 1 && (status == 4 || status == 16))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
return (cc) ? -EIO : 0;
|
return (cc) ? -EIO : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue