s390/pci: unify de-/configure for slots and events
authorNiklas Schnelle <schnelle@linux.ibm.com>
Tue, 3 Nov 2020 09:41:20 +0000 (10:41 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 22 Mar 2021 10:36:04 +0000 (11:36 +0100)
A zPCI event with PEC 0x0301 for an existing zPCI device goes through
the same actions as enable_slot(). Similarly a zPCI event with PEC
0x0303 does the same steps as disable_slot().
We can thus unify both actions as zpci_configure_device() respectively
zpci_deconfigure_device().

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/include/asm/pci.h
arch/s390/pci/pci.c
arch/s390/pci/pci_event.c
drivers/pci/hotplug/s390_pci_hpc.c

index 5ed1193..c454dfb 100644 (file)
@@ -204,6 +204,9 @@ int zpci_create_device(u32 fid, u32 fh, enum zpci_state state);
 void zpci_remove_device(struct zpci_dev *zdev, bool set_error);
 int zpci_enable_device(struct zpci_dev *);
 int zpci_disable_device(struct zpci_dev *);
+int zpci_configure_device(struct zpci_dev *zdev, u32 fh);
+int zpci_deconfigure_device(struct zpci_dev *zdev);
+
 int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
 int zpci_unregister_ioat(struct zpci_dev *, u8);
 void zpci_remove_reserved_devices(void);
index 5d6b838..6d84ec8 100644 (file)
@@ -668,7 +668,6 @@ out_dma:
 out:
        return rc;
 }
-EXPORT_SYMBOL_GPL(zpci_enable_device);
 
 int zpci_disable_device(struct zpci_dev *zdev)
 {
@@ -679,7 +678,6 @@ int zpci_disable_device(struct zpci_dev *zdev)
         */
        return clp_disable_fh(zdev);
 }
-EXPORT_SYMBOL_GPL(zpci_disable_device);
 
 /* zpci_remove_device - Removes the given zdev from the PCI core
  * @zdev: the zdev to be removed from the PCI core
@@ -779,6 +777,93 @@ error:
        return rc;
 }
 
+/**
+ * zpci_configure_device() - Configure a zpci_dev
+ * @zdev: The zpci_dev to be configured
+ * @fh: The general function handle supplied by the platform
+ *
+ * Configuring a device includes the configuration itself, if not done by the
+ * platform, enabling, scanning and adding it to the common code PCI subsystem.
+ * If any failure occurs, the zpci_dev is left in Standby.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int zpci_configure_device(struct zpci_dev *zdev, u32 fh)
+{
+       struct pci_dev *pdev;
+       int rc;
+
+       zdev->fh = fh;
+       if (zdev->state != ZPCI_FN_STATE_CONFIGURED) {
+               rc = sclp_pci_configure(zdev->fid);
+               zpci_dbg(3, "conf fid:%x, rc:%d\n", zdev->fid, rc);
+               if (rc)
+                       return rc;
+               zdev->state = ZPCI_FN_STATE_CONFIGURED;
+       }
+
+       rc = zpci_enable_device(zdev);
+       if (rc)
+               goto error;
+
+       /* the PCI function will be scanned once function 0 appears */
+       if (!zdev->zbus->bus)
+               return 0;
+
+       pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
+       if (!pdev)
+               goto error_disable;
+
+       pci_bus_add_device(pdev);
+       pci_lock_rescan_remove();
+       pci_bus_add_devices(zdev->zbus->bus);
+       pci_unlock_rescan_remove();
+       return 0;
+
+error_disable:
+       zpci_disable_device(zdev);
+error:
+       if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
+               rc = sclp_pci_deconfigure(zdev->fid);
+               zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, rc);
+               if (!rc)
+                       zdev->state = ZPCI_FN_STATE_STANDBY;
+       }
+       return rc;
+}
+
+/**
+ * zpci_deconfigure_device() - Deconfigure a zpci_dev
+ * @zdev: The zpci_dev to configure
+ *
+ * Deconfigure a zPCI function that is currently configured and possibly known
+ * to the common code PCI subsystem.
+ * If any failure occurs the device is left as is.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int zpci_deconfigure_device(struct zpci_dev *zdev)
+{
+       int rc;
+
+       if (zdev->zbus->bus)
+               zpci_remove_device(zdev, false);
+
+       if (zdev_enabled(zdev)) {
+               rc = zpci_disable_device(zdev);
+               if (rc)
+                       return rc;
+       }
+
+       rc = sclp_pci_deconfigure(zdev->fid);
+       zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, rc);
+       if (rc)
+               return rc;
+       zdev->state = ZPCI_FN_STATE_STANDBY;
+
+       return 0;
+}
+
 void zpci_release_device(struct kref *kref)
 {
        struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
index 0474ff8..2676df9 100644 (file)
@@ -98,8 +98,6 @@ static void zpci_event_hard_deconfigured(struct zpci_dev *zdev, u32 fh)
 static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
 {
        struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
-       struct pci_dev *pdev;
-       int ret;
 
        zpci_err("avail CCDF:\n");
        zpci_err_hex(ccdf, sizeof(*ccdf));
@@ -113,46 +111,20 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
                /* the configuration request may be stale */
                if (zdev->state != ZPCI_FN_STATE_STANDBY)
                        break;
-               zdev->fh = ccdf->fh;
                zdev->state = ZPCI_FN_STATE_CONFIGURED;
-               ret = zpci_enable_device(zdev);
-               if (ret)
-                       break;
-
-               /* the PCI function will be scanned once function 0 appears */
-               if (!zdev->zbus->bus)
-                       break;
-
-               pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
-               if (!pdev)
-                       break;
-
-               pci_bus_add_device(pdev);
-               pci_lock_rescan_remove();
-               pci_bus_add_devices(zdev->zbus->bus);
-               pci_unlock_rescan_remove();
+               zpci_configure_device(zdev, ccdf->fh);
                break;
        case 0x0302: /* Reserved -> Standby */
-               if (!zdev) {
+               if (!zdev)
                        zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY);
-                       break;
-               }
-               zdev->fh = ccdf->fh;
+               else
+                       zdev->fh = ccdf->fh;
                break;
        case 0x0303: /* Deconfiguration requested */
-               if (!zdev)
-                       break;
-               zpci_remove_device(zdev, false);
-
-               ret = zpci_disable_device(zdev);
-               if (ret)
-                       break;
-
-               ret = sclp_pci_deconfigure(zdev->fid);
-               zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
-               if (!ret)
-                       zdev->state = ZPCI_FN_STATE_STANDBY;
-
+               if (zdev) {
+                       zdev->fh = ccdf->fh;
+                       zpci_deconfigure_device(zdev);
+               }
                break;
        case 0x0304: /* Configured -> Standby|Reserved */
                if (zdev)
index c93c09a..1545326 100644 (file)
 
 #define SLOT_NAME_SIZE 10
 
-static inline int zdev_configure(struct zpci_dev *zdev)
-{
-       int ret = sclp_pci_configure(zdev->fid);
-
-       zpci_dbg(3, "conf fid:%x, rc:%d\n", zdev->fid, ret);
-       if (!ret)
-               zdev->state = ZPCI_FN_STATE_CONFIGURED;
-
-       return ret;
-}
-
-static inline int zdev_deconfigure(struct zpci_dev *zdev)
-{
-       int ret = sclp_pci_deconfigure(zdev->fid);
-
-       zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
-       if (!ret)
-               zdev->state = ZPCI_FN_STATE_STANDBY;
-
-       return ret;
-}
-
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
                                             hotplug_slot);
-       struct zpci_bus *zbus = zdev->zbus;
-       int rc;
 
        if (zdev->state != ZPCI_FN_STATE_STANDBY)
                return -EIO;
 
-       rc = zdev_configure(zdev);
-       if (rc)
-               return rc;
-
-       rc = zpci_enable_device(zdev);
-       if (rc)
-               goto out_deconfigure;
-
-       pci_scan_slot(zbus->bus, zdev->devfn);
-       pci_lock_rescan_remove();
-       pci_bus_add_devices(zbus->bus);
-       pci_unlock_rescan_remove();
-
-       return rc;
-
-out_deconfigure:
-       zdev_deconfigure(zdev);
-       return rc;
+       return zpci_configure_device(zdev, zdev->fh);
 }
 
 static int disable_slot(struct hotplug_slot *hotplug_slot)
@@ -77,7 +36,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
        struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
                                             hotplug_slot);
        struct pci_dev *pdev;
-       int rc;
 
        if (zdev->state != ZPCI_FN_STATE_CONFIGURED)
                return -EIO;
@@ -89,13 +47,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
        }
        pci_dev_put(pdev);
 
-       zpci_remove_device(zdev, false);
-
-       rc = zpci_disable_device(zdev);
-       if (rc)
-               return rc;
-
-       return zdev_deconfigure(zdev);
+       return zpci_deconfigure_device(zdev);
 }
 
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)