summaryrefslogtreecommitdiff
path: root/arch/s390/pci/pci.c
diff options
context:
space:
mode:
authorNiklas Schnelle <schnelle@linux.ibm.com>2021-07-16 11:53:37 +0200
committerHeiko Carstens <hca@linux.ibm.com>2021-08-25 11:03:34 +0200
commit1f3f76812d5dfc791193b39c2140a8bd09962c0e (patch)
tree8f61dd33029e218e765af3ad8753856ad6d5881b /arch/s390/pci/pci.c
parentcc049eecfb7adc4bfecd05eb25e425d8def96fce (diff)
s390/pci: improve DMA translation init and exit
Currently zpci_dma_init_device()/zpci_dma_exit_device() is called as part of zpci_enable_device()/zpci_disable_device() and errors for zpci_dma_exit_device() are always ignored even if we could abort. Improve upon this by moving zpci_dma_exit_device() out of zpci_disable_device() and check for errors whenever we have a way to abort the current operation. Note that for example in zpci_event_hard_deconfigured() the device is expected to be gone so we really can't abort and proceed even in case of error. Similarly move the cc == 3 special case out of zpci_unregister_ioat() and into the callers allowing to abort when finding an already disabled devices precludes proceeding with the operation. While we are at it log IOAT register/unregister errors in the s390 debugfs log, Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r--arch/s390/pci/pci.c43
1 files changed, 19 insertions, 24 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index b05b86e2d2c0..728508da999d 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -113,13 +113,16 @@ int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
{
u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, ZPCI_MOD_FC_REG_IOAT);
struct zpci_fib fib = {0};
- u8 status;
+ u8 cc, status;
WARN_ON_ONCE(iota & 0x3fff);
fib.pba = base;
fib.pal = limit;
fib.iota = iota | ZPCI_IOTA_RTTO_FLAG;
- return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
+ cc = zpci_mod_fc(req, &fib, &status);
+ if (cc)
+ zpci_dbg(3, "reg ioat fid:%x, cc:%d, status:%d\n", zdev->fid, cc, status);
+ return cc;
}
/* Modify PCI: Unregister I/O address translation parameters */
@@ -130,9 +133,9 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
u8 cc, status;
cc = zpci_mod_fc(req, &fib, &status);
- if (cc == 3) /* Function already gone. */
- cc = 0;
- return cc ? -EIO : 0;
+ if (cc)
+ zpci_dbg(3, "unreg ioat fid:%x, cc:%d, status:%d\n", zdev->fid, cc, status);
+ return cc;
}
/* Modify PCI: Set PCI function measurement parameters */
@@ -654,24 +657,12 @@ void zpci_free_domain(int domain)
int zpci_enable_device(struct zpci_dev *zdev)
{
u32 fh = zdev->fh;
- int rc;
+ int rc = 0;
- if (clp_enable_fh(zdev, &fh, ZPCI_NR_DMA_SPACES)) {
+ if (clp_enable_fh(zdev, &fh, ZPCI_NR_DMA_SPACES))
rc = -EIO;
- goto out;
- }
- zdev->fh = fh;
-
- rc = zpci_dma_init_device(zdev);
- if (rc)
- goto out_dma;
-
- return 0;
-
-out_dma:
- clp_disable_fh(zdev, &fh);
-out:
- zdev->fh = fh;
+ else
+ zdev->fh = fh;
return rc;
}
@@ -680,9 +671,6 @@ int zpci_disable_device(struct zpci_dev *zdev)
u32 fh = zdev->fh;
int cc, rc = 0;
- zpci_dma_exit_device(zdev);
- if (!zdev_enabled(zdev))
- return 0;
cc = clp_disable_fh(zdev, &fh);
if (!cc) {
zdev->fh = fh;
@@ -808,6 +796,11 @@ int zpci_deconfigure_device(struct zpci_dev *zdev)
if (zdev->zbus->bus)
zpci_bus_remove_device(zdev, false);
+ if (zdev->dma_table) {
+ rc = zpci_dma_exit_device(zdev);
+ if (rc)
+ return rc;
+ }
if (zdev_enabled(zdev)) {
rc = zpci_disable_device(zdev);
if (rc)
@@ -831,6 +824,8 @@ void zpci_release_device(struct kref *kref)
if (zdev->zbus->bus)
zpci_bus_remove_device(zdev, false);
+ if (zdev->dma_table)
+ zpci_dma_exit_device(zdev);
if (zdev_enabled(zdev))
zpci_disable_device(zdev);