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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+87 −2
Original line number Diff line number Diff line
@@ -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);
+8 −36
Original line number Diff line number Diff line
@@ -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;
		}
		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)
+2 −50
Original line number Diff line number Diff line
@@ -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)