summaryrefslogtreecommitdiff
path: root/arch/s390/pci
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2017-06-10 14:12:13 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2017-06-28 07:32:10 +0200
commit4e5bd7803bd1e822513d1007bad1527a2ec589b6 (patch)
treebc9e07a9c933b3935e0f7849c6c47a2398c75414 /arch/s390/pci
parent725708349172f00b86e2bac5c03de360b79aaf65 (diff)
s390/pci: improve error handling during fmb (de)registration
Cleanup in zpci_fmb_enable_device when fmb registration fails. Also don't free the fmb when deregistration fails in zpci_fmb_disable_device but handle error situations when a function was hot-unplugged. Also remove the mod_pci helper since it is no longer used. 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>
Diffstat (limited to 'arch/s390/pci')
-rw-r--r--arch/s390/pci/pci.c51
1 files changed, 21 insertions, 30 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 4f541f54470f..6a44a68efb81 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -136,27 +136,6 @@ static int zpci_clear_airq(struct zpci_dev *zdev)
return cc ? -EIO : 0;
}
-struct mod_pci_args {
- u64 base;
- u64 limit;
- u64 iota;
- u64 fmb_addr;
-};
-
-static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args)
-{
- u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, fn);
- struct zpci_fib fib = {0};
- u8 status;
-
- fib.pba = args->base;
- fib.pal = args->limit;
- fib.iota = args->iota;
- fib.fmb_addr = args->fmb_addr;
-
- return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
-}
-
/* Modify PCI: Register I/O address translation parameters */
int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas,
u64 base, u64 limit, u64 iota)
@@ -188,7 +167,9 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
/* Modify PCI: Set PCI function measurement parameters */
int zpci_fmb_enable_device(struct zpci_dev *zdev)
{
- struct mod_pci_args args = { 0, 0, 0, 0 };
+ u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_SET_MEASURE);
+ struct zpci_fib fib = {0};
+ u8 cc, status;
if (zdev->fmb || sizeof(*zdev->fmb) < zdev->fmb_length)
return -EINVAL;
@@ -203,25 +184,35 @@ int zpci_fmb_enable_device(struct zpci_dev *zdev)
atomic64_set(&zdev->mapped_pages, 0);
atomic64_set(&zdev->unmapped_pages, 0);
- args.fmb_addr = virt_to_phys(zdev->fmb);
- return mod_pci(zdev, ZPCI_MOD_FC_SET_MEASURE, 0, &args);
+ fib.fmb_addr = virt_to_phys(zdev->fmb);
+ cc = zpci_mod_fc(req, &fib, &status);
+ if (cc) {
+ kmem_cache_free(zdev_fmb_cache, zdev->fmb);
+ zdev->fmb = NULL;
+ }
+ return cc ? -EIO : 0;
}
/* Modify PCI: Disable PCI function measurement */
int zpci_fmb_disable_device(struct zpci_dev *zdev)
{
- struct mod_pci_args args = { 0, 0, 0, 0 };
- int rc;
+ u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_SET_MEASURE);
+ struct zpci_fib fib = {0};
+ u8 cc, status;
if (!zdev->fmb)
return -EINVAL;
/* Function measurement is disabled if fmb address is zero */
- rc = mod_pci(zdev, ZPCI_MOD_FC_SET_MEASURE, 0, &args);
+ cc = zpci_mod_fc(req, &fib, &status);
+ if (cc == 3) /* Function already gone. */
+ cc = 0;
- kmem_cache_free(zdev_fmb_cache, zdev->fmb);
- zdev->fmb = NULL;
- return rc;
+ if (!cc) {
+ kmem_cache_free(zdev_fmb_cache, zdev->fmb);
+ zdev->fmb = NULL;
+ }
+ return cc ? -EIO : 0;
}
static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len)