Commit b804e8a6 authored by Jing Liu's avatar Jing Liu Committed by Cornelia Huck
Browse files

s390x/css: Unplug handler of virtual css bridge



The previous patch moved virtual css bridge and bus out from
virtio-ccw, but kept the direct reference of virtio-ccw specific
unplug function inside css-bridge.c.

To make the virtual css bus and bridge useful for non-virtio devices,
this introduces a common unplug function pointer "unplug" to call
specific virtio-ccw unplug parts. Thus, the tight coupling to
virtio-ccw can be removed.

This unplug pointer is a member of CCWDeviceClass, which is introduced
as an abstract device layer called "ccw-device". This layer is between
DeviceState and specific devices which are plugged in virtual css bus,
like virtio-ccw device. The specific unplug handlers should be assigned
to "unplug" during initialization.

Signed-off-by: default avatarJing Liu <liujbjl@linux.vnet.ibm.com>
Reviewed-by: default avatarSascha Silbe <silbe@linux.vnet.ibm.com>
Reviewed-by: default avatarDong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
Reviewed-by: default avatarYi Min Zhao <zyimin@linux.vnet.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent dd70bd0d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ obj-y += css.o
obj-y += s390-virtio-ccw.o
obj-y += virtio-ccw.o
obj-y += css-bridge.o
obj-y += ccw-device.o
obj-y += s390-pci-bus.o s390-pci-inst.o
obj-y += s390-skeys.o
obj-$(CONFIG_KVM) += s390-skeys-kvm.o

hw/s390x/ccw-device.c

0 → 100644
+27 −0
Original line number Diff line number Diff line
/*
 * Common device infrastructure for devices in the virtual css
 *
 * Copyright 2016 IBM Corp.
 * Author(s): Jing Liu <liujbjl@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 * your option) any later version. See the COPYING file in the top-level
 * directory.
 */
#include "qemu/osdep.h"
#include "ccw-device.h"

static const TypeInfo ccw_device_info = {
    .name = TYPE_CCW_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(CcwDevice),
    .class_size = sizeof(CCWDeviceClass),
    .abstract = true,
};

static void ccw_device_register(void)
{
    type_register_static(&ccw_device_info);
}

type_init(ccw_device_register)

hw/s390x/ccw-device.h

0 → 100644
+43 −0
Original line number Diff line number Diff line
/*
 * Common device infrastructure for devices in the virtual css
 *
 * Copyright 2016 IBM Corp.
 * Author(s): Jing Liu <liujbjl@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 * your option) any later version. See the COPYING file in the top-level
 * directory.
 */

#ifndef HW_S390X_CCW_DEVICE_H
#define HW_S390X_CCW_DEVICE_H
#include "qom/object.h"
#include "hw/qdev-core.h"
#include "hw/s390x/css.h"

typedef struct CcwDevice {
    DeviceState parent_obj;
    SubchDev *sch;
    /* <cssid>.<ssid>.<device number> */
    CssDevId bus_id;
} CcwDevice;

typedef struct CCWDeviceClass {
    DeviceClass parent_class;
    void (*unplug)(HotplugHandler *, DeviceState *, Error **);
} CCWDeviceClass;

static inline CcwDevice *to_ccw_dev_fast(DeviceState *d)
{
    return container_of(d, CcwDevice, parent_obj);
}

#define TYPE_CCW_DEVICE "ccw-device"

#define CCW_DEVICE(obj) OBJECT_CHECK(CcwDevice, (obj), TYPE_CCW_DEVICE)
#define CCW_DEVICE_GET_CLASS(obj) \
    OBJECT_GET_CLASS(CCWDeviceClass, (obj), TYPE_CCW_DEVICE)
#define CCW_DEVICE_CLASS(klass) \
    OBJECT_CLASS_CHECK(CCWDeviceClass, (klass), TYPE_CCW_DEVICE)

#endif
+37 −2
Original line number Diff line number Diff line
@@ -11,13 +11,48 @@
 */
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "virtio-ccw.h"
#include "hw/hotplug.h"
#include "hw/sysbus.h"
#include "qemu/bitops.h"
#include "hw/s390x/css.h"
#include "ccw-device.h"
#include "hw/s390x/css-bridge.h"

/*
 * Invoke device-specific unplug handler, disable the subchannel
 * (including sending a channel report to the guest) and remove the
 * device from the virtual css bus.
 */
static void ccw_device_unplug(HotplugHandler *hotplug_dev,
                              DeviceState *dev, Error **errp)
{
    CcwDevice *ccw_dev = CCW_DEVICE(dev);
    CCWDeviceClass *k = CCW_DEVICE_GET_CLASS(ccw_dev);
    SubchDev *sch = ccw_dev->sch;
    Error *err = NULL;

    if (k->unplug) {
        k->unplug(hotplug_dev, dev, &err);
        if (err) {
            error_propagate(errp, err);
            return;
        }
    }

    /*
     * We should arrive here only for device_del, since we don't support
     * direct hot(un)plug of channels.
     */
    assert(sch != NULL);
    /* Subchannel is now disabled and no longer valid. */
    sch->curr_status.pmcw.flags &= ~(PMCW_FLAGS_MASK_ENA |
                                     PMCW_FLAGS_MASK_DNV);

    css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid, 1, 0);

    object_unparent(OBJECT(dev));
}

static void virtual_css_bus_reset(BusState *qbus)
{
    /* This should actually be modelled via the generic css */
@@ -65,7 +100,7 @@ static void virtual_css_bridge_class_init(ObjectClass *klass, void *data)
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    hc->unplug = virtio_ccw_busdev_unplug;
    hc->unplug = ccw_device_unplug;
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
}

+8 −6
Original line number Diff line number Diff line
@@ -221,12 +221,14 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)

    dev_st = get_boot_device(0);
    if (dev_st) {
        VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
            OBJECT(qdev_get_parent_bus(dev_st)->parent),
        VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
            object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
                TYPE_VIRTIO_CCW_DEVICE);
        SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
                                                            TYPE_SCSI_DEVICE);
        if (ccw_dev) {
        if (virtio_ccw_dev) {
            CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev);

            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
            ipl->iplb.blk0_len =
                cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
@@ -238,7 +240,7 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
            SCSIBus *bus = scsi_bus_from_device(sd);
            VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
            VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
            VirtioCcwDevice *ccw = &scsi_ccw->parent_obj;
            CcwDevice *ccw_dev = CCW_DEVICE(scsi_ccw);

            ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
            ipl->iplb.blk0_len =
@@ -247,8 +249,8 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
            ipl->iplb.scsi.lun = cpu_to_be32(sd->lun);
            ipl->iplb.scsi.target = cpu_to_be16(sd->id);
            ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
            ipl->iplb.scsi.devno = cpu_to_be16(ccw->sch->devno);
            ipl->iplb.scsi.ssid = ccw->sch->ssid & 3;
            ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
            ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
            return true;
        }
    }
Loading