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>
This commit is contained in:
Родитель
a4f17cc726
Коммит
2631f6b6f2
|
@ -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 @@ 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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче