s390/pci: improve unreg_ioat error handling
DMA tables are freed in zpci_dma_exit_device regardless of the return code of zpci_unregister_ioat. This could lead to a use after free. On the other hand during function hot-unplug, zpci_unregister_ioat will always fail since the function is already gone. So let zpci_unregister_ioat report success when the function is gone but don't cleanup the dma table when a function could still have it in access. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>hifive-unleashed-5.1
parent
4dfbd3efe3
commit
7257083491
|
@ -161,19 +161,28 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
|
||||||
int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
|
int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
|
||||||
u64 base, u64 limit, u64 iota)
|
u64 base, u64 limit, u64 iota)
|
||||||
{
|
{
|
||||||
struct mod_pci_args args = { base, limit, iota, 0 };
|
u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_REG_IOAT);
|
||||||
|
struct zpci_fib fib = {0};
|
||||||
|
u8 status;
|
||||||
|
|
||||||
WARN_ON_ONCE(iota & 0x3fff);
|
WARN_ON_ONCE(iota & 0x3fff);
|
||||||
args.iota |= ZPCI_IOTA_RTTO_FLAG;
|
fib.pba = base;
|
||||||
return mod_pci(zdev, ZPCI_MOD_FC_REG_IOAT, dmaas, &args);
|
fib.pal = limit;
|
||||||
|
fib.iota = iota | ZPCI_IOTA_RTTO_FLAG;
|
||||||
|
return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modify PCI: Unregister I/O address translation parameters */
|
/* Modify PCI: Unregister I/O address translation parameters */
|
||||||
int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
|
int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
|
||||||
{
|
{
|
||||||
struct mod_pci_args args = { 0, 0, 0, 0 };
|
u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_DEREG_IOAT);
|
||||||
|
struct zpci_fib fib = {0};
|
||||||
|
u8 cc, status;
|
||||||
|
|
||||||
return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args);
|
cc = zpci_mod_fc(req, &fib, &status);
|
||||||
|
if (cc == 3) /* Function already gone. */
|
||||||
|
cc = 0;
|
||||||
|
return cc ? -EIO : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modify PCI: Set PCI function measurement parameters */
|
/* Modify PCI: Set PCI function measurement parameters */
|
||||||
|
|
|
@ -601,7 +601,9 @@ void zpci_dma_exit_device(struct zpci_dev *zdev)
|
||||||
*/
|
*/
|
||||||
WARN_ON(zdev->s390_domain);
|
WARN_ON(zdev->s390_domain);
|
||||||
|
|
||||||
zpci_unregister_ioat(zdev, 0);
|
if (zpci_unregister_ioat(zdev, 0))
|
||||||
|
return;
|
||||||
|
|
||||||
dma_cleanup_tables(zdev->dma_table);
|
dma_cleanup_tables(zdev->dma_table);
|
||||||
zdev->dma_table = NULL;
|
zdev->dma_table = NULL;
|
||||||
vfree(zdev->iommu_bitmap);
|
vfree(zdev->iommu_bitmap);
|
||||||
|
|
Loading…
Reference in New Issue