diff options
author | Niklas Schnelle <schnelle@linux.ibm.com> | 2020-11-03 12:41:20 +0300 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2021-03-22 13:36:04 +0300 |
commit | 2631f6b6f22ca613238a416a09e3d2771def6f88 (patch) | |
tree | 9ab0b08d9edc24ec45b8c4f20a4e3721a77d8ed1 /arch/s390/pci/pci.c | |
parent | a4f17cc726712a52122ad38540bc3ff3a052d1a4 (diff) | |
download | linux-2631f6b6f22ca613238a416a09e3d2771def6f88.tar.xz |
s390/pci: unify de-/configure for slots and events
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>
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r-- | arch/s390/pci/pci.c | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 5d6b838c0f22..6d84ec8f1dd6 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -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); |