s390/pci: fix misleading rc in clp_set_pci_fn()
authorNiklas Schnelle <schnelle@linux.ibm.com>
Wed, 21 Jul 2021 17:58:54 +0000 (19:58 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 25 Aug 2021 09:03:33 +0000 (11:03 +0200)
Currently clp_set_pci_fn() always returns 0 as long as the CLP request
itself succeeds even if the operation itself returns a response code
other than CLP_RC_OK or CLP_RC_SETPCIFN_ALRDY. This is highly misleading
because calling code assumes that a zero rc means that the operation was
successful.

Fix this by returning the response code or cc on failure with the
exception of the special handling for CLP_RC_SETPCIFN_ALRDY. Also let's
not assume that the returned function handle for CLP_RC_SETPCIFN_ALRDY
is 0, we don't need it anyway.

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>
arch/s390/pci/pci.c
arch/s390/pci/pci_clp.c

index 67dc5b1..4eafa81 100644 (file)
@@ -655,9 +655,10 @@ int zpci_enable_device(struct zpci_dev *zdev)
 {
        int rc;
 
-       rc = clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES);
-       if (rc)
+       if (clp_enable_fh(zdev, ZPCI_NR_DMA_SPACES)) {
+               rc = -EIO;
                goto out;
+       }
 
        rc = zpci_dma_init_device(zdev);
        if (rc)
@@ -678,7 +679,7 @@ int zpci_disable_device(struct zpci_dev *zdev)
         * The zPCI function may already be disabled by the platform, this is
         * detected in clp_disable_fh() which becomes a no-op.
         */
-       return clp_disable_fh(zdev);
+       return clp_disable_fh(zdev) ? -EIO : 0;
 }
 
 /**
index d333159..0a0e8b8 100644 (file)
@@ -213,15 +213,19 @@ out:
 }
 
 static int clp_refresh_fh(u32 fid);
-/*
- * Enable/Disable a given PCI function and update its function handle if
- * necessary
+/**
+ * clp_set_pci_fn() - Execute a command on a PCI function
+ * @zdev: Function that will be affected
+ * @nr_dma_as: DMA address space number
+ * @command: The command code to execute
+ *
+ * Returns: 0 on success, < 0 for Linux errors (e.g. -ENOMEM), and
+ * > 0 for non-success platform responses
  */
 static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
 {
        struct clp_req_rsp_set_pci *rrb;
        int rc, retries = 100;
-       u32 fid = zdev->fid;
 
        rrb = clp_alloc_block(GFP_KERNEL);
        if (!rrb)
@@ -245,17 +249,16 @@ static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
                }
        } while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);
 
-       if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
-               zpci_err("Set PCI FN:\n");
-               zpci_err_clp(rrb->response.hdr.rsp, rc);
-       }
-
        if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
                zdev->fh = rrb->response.fh;
-       } else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY &&
-                       rrb->response.fh == 0) {
+       } else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY) {
                /* Function is already in desired state - update handle */
-               rc = clp_refresh_fh(fid);
+               rc = clp_refresh_fh(zdev->fid);
+       } else {
+               zpci_err("Set PCI FN:\n");
+               zpci_err_clp(rrb->response.hdr.rsp, rc);
+               if (!rc)
+                       rc = rrb->response.hdr.rsp;
        }
        clp_free_block(rrb);
        return rc;
@@ -301,17 +304,13 @@ int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
 
        rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
        zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
-       if (rc)
-               goto out;
-
-       if (zpci_use_mio(zdev)) {
+       if (!rc && zpci_use_mio(zdev)) {
                rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_MIO);
                zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n",
                                zdev->fid, zdev->fh, rc);
                if (rc)
                        clp_disable_fh(zdev);
        }
-out:
        return rc;
 }