Commit 2631f6b6 authored by Niklas Schnelle's avatar Niklas Schnelle Committed by Heiko Carstens

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: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
parent a4f17cc7
......@@ -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);
......
......@@ -668,7 +668,6 @@ int zpci_enable_device(struct zpci_dev *zdev)
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 @@ int zpci_create_device(u32 fid, u32 fh, enum zpci_state state)
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);
......
......@@ -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)
......
......@@ -20,56 +20,15 @@
#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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment