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: Jing Liu <liujbjl@linux.vnet.ibm.com> Reviewed-by: Sascha Silbe <silbe@linux.vnet.ibm.com> Reviewed-by: Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com> Reviewed-by: Yi Min Zhao <zyimin@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
dd70bd0d4c
commit
b804e8a62a
|
@ -9,6 +9,7 @@ obj-y += css.o
|
||||||
obj-y += s390-virtio-ccw.o
|
obj-y += s390-virtio-ccw.o
|
||||||
obj-y += virtio-ccw.o
|
obj-y += virtio-ccw.o
|
||||||
obj-y += css-bridge.o
|
obj-y += css-bridge.o
|
||||||
|
obj-y += ccw-device.o
|
||||||
obj-y += s390-pci-bus.o s390-pci-inst.o
|
obj-y += s390-pci-bus.o s390-pci-inst.o
|
||||||
obj-y += s390-skeys.o
|
obj-y += s390-skeys.o
|
||||||
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
|
obj-$(CONFIG_KVM) += s390-skeys-kvm.o
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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)
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* 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
|
|
@ -11,13 +11,48 @@
|
||||||
*/
|
*/
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "virtio-ccw.h"
|
|
||||||
#include "hw/hotplug.h"
|
#include "hw/hotplug.h"
|
||||||
#include "hw/sysbus.h"
|
#include "hw/sysbus.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
#include "hw/s390x/css.h"
|
#include "hw/s390x/css.h"
|
||||||
|
#include "ccw-device.h"
|
||||||
#include "hw/s390x/css-bridge.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)
|
static void virtual_css_bus_reset(BusState *qbus)
|
||||||
{
|
{
|
||||||
/* This should actually be modelled via the generic css */
|
/* 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);
|
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
|
||||||
DeviceClass *dc = DEVICE_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);
|
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,12 +221,14 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
|
||||||
|
|
||||||
dev_st = get_boot_device(0);
|
dev_st = get_boot_device(0);
|
||||||
if (dev_st) {
|
if (dev_st) {
|
||||||
VirtioCcwDevice *ccw_dev = (VirtioCcwDevice *) object_dynamic_cast(
|
VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *)
|
||||||
OBJECT(qdev_get_parent_bus(dev_st)->parent),
|
object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent),
|
||||||
TYPE_VIRTIO_CCW_DEVICE);
|
TYPE_VIRTIO_CCW_DEVICE);
|
||||||
SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
|
SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st),
|
||||||
TYPE_SCSI_DEVICE);
|
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.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
|
||||||
ipl->iplb.blk0_len =
|
ipl->iplb.blk0_len =
|
||||||
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_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);
|
SCSIBus *bus = scsi_bus_from_device(sd);
|
||||||
VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
|
VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
|
||||||
VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
|
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.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
|
||||||
ipl->iplb.blk0_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.lun = cpu_to_be32(sd->lun);
|
||||||
ipl->iplb.scsi.target = cpu_to_be16(sd->id);
|
ipl->iplb.scsi.target = cpu_to_be16(sd->id);
|
||||||
ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
|
ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
|
||||||
ipl->iplb.scsi.devno = cpu_to_be16(ccw->sch->devno);
|
ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||||
ipl->iplb.scsi.ssid = ccw->sch->ssid & 3;
|
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,8 @@ static int virtio_ccw_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
|
||||||
int n, bool assign)
|
int n, bool assign)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
SubchDev *sch = dev->sch;
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
||||||
|
SubchDev *sch = ccw_dev->sch;
|
||||||
uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
|
uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
|
||||||
|
|
||||||
return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
|
return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
|
||||||
|
@ -194,6 +195,8 @@ static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
|
||||||
|
|
||||||
static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
|
static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
|
||||||
{
|
{
|
||||||
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
||||||
|
|
||||||
virtio_ccw_stop_ioeventfd(dev);
|
virtio_ccw_stop_ioeventfd(dev);
|
||||||
virtio_reset(vdev);
|
virtio_reset(vdev);
|
||||||
if (dev->indicators) {
|
if (dev->indicators) {
|
||||||
|
@ -208,7 +211,7 @@ static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
|
||||||
release_indicator(&dev->routes.adapter, dev->summary_indicator);
|
release_indicator(&dev->routes.adapter, dev->summary_indicator);
|
||||||
dev->summary_indicator = NULL;
|
dev->summary_indicator = NULL;
|
||||||
}
|
}
|
||||||
dev->sch->thinint_active = false;
|
ccw_dev->sch->thinint_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
|
static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
|
||||||
|
@ -664,7 +667,8 @@ static void virtio_sch_disable_cb(SubchDev *sch)
|
||||||
static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
|
static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
|
VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
|
||||||
SubchDev *sch = css_create_virtual_sch(dev->bus_id, errp);
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
||||||
|
SubchDev *sch = css_create_virtual_sch(ccw_dev->bus_id, errp);
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
if (!sch) {
|
if (!sch) {
|
||||||
|
@ -676,14 +680,14 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
|
||||||
sch->disable_cb = virtio_sch_disable_cb;
|
sch->disable_cb = virtio_sch_disable_cb;
|
||||||
sch->id.reserved = 0xff;
|
sch->id.reserved = 0xff;
|
||||||
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
|
sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
|
||||||
dev->sch = sch;
|
ccw_dev->sch = sch;
|
||||||
dev->indicators = NULL;
|
dev->indicators = NULL;
|
||||||
dev->revision = -1;
|
dev->revision = -1;
|
||||||
css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
|
css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
|
||||||
|
|
||||||
trace_virtio_ccw_new_device(
|
trace_virtio_ccw_new_device(
|
||||||
sch->cssid, sch->ssid, sch->schid, sch->devno,
|
sch->cssid, sch->ssid, sch->schid, sch->devno,
|
||||||
dev->bus_id.valid ? "user-configured" : "auto-configured");
|
ccw_dev->bus_id.valid ? "user-configured" : "auto-configured");
|
||||||
|
|
||||||
if (k->realize) {
|
if (k->realize) {
|
||||||
k->realize(dev, &err);
|
k->realize(dev, &err);
|
||||||
|
@ -691,14 +695,15 @@ static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
|
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
|
||||||
dev->sch = NULL;
|
ccw_dev->sch = NULL;
|
||||||
g_free(sch);
|
g_free(sch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_ccw_exit(VirtioCcwDevice *dev)
|
static int virtio_ccw_exit(VirtioCcwDevice *dev)
|
||||||
{
|
{
|
||||||
SubchDev *sch = dev->sch;
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
||||||
|
SubchDev *sch = ccw_dev->sch;
|
||||||
|
|
||||||
if (sch) {
|
if (sch) {
|
||||||
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
|
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
|
||||||
|
@ -879,7 +884,9 @@ static void virtio_ccw_rng_realize(VirtioCcwDevice *ccw_dev, Error **errp)
|
||||||
*/
|
*/
|
||||||
static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
|
static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
|
||||||
{
|
{
|
||||||
return container_of(d, VirtioCcwDevice, parent_obj);
|
CcwDevice *ccw_dev = to_ccw_dev_fast(d);
|
||||||
|
|
||||||
|
return container_of(ccw_dev, VirtioCcwDevice, parent_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
|
static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
|
||||||
|
@ -908,7 +915,8 @@ static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
|
||||||
static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
|
static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
|
VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
|
||||||
SubchDev *sch = dev->sch;
|
CcwDevice *ccw_dev = to_ccw_dev_fast(d);
|
||||||
|
SubchDev *sch = ccw_dev->sch;
|
||||||
uint64_t indicators;
|
uint64_t indicators;
|
||||||
|
|
||||||
/* queue indicators + secondary indicators */
|
/* queue indicators + secondary indicators */
|
||||||
|
@ -966,9 +974,10 @@ static void virtio_ccw_reset(DeviceState *d)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
||||||
|
CcwDevice *ccw_dev = CCW_DEVICE(d);
|
||||||
|
|
||||||
virtio_ccw_reset_virtio(dev, vdev);
|
virtio_ccw_reset_virtio(dev, vdev);
|
||||||
css_reset_sch(dev->sch);
|
css_reset_sch(ccw_dev->sch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
|
static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
|
||||||
|
@ -984,7 +993,7 @@ static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
|
||||||
|
|
||||||
static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
|
static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
CcwDevice *dev = CCW_DEVICE(d);
|
||||||
|
|
||||||
return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
|
return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
|
||||||
}
|
}
|
||||||
|
@ -992,8 +1001,9 @@ static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
|
||||||
static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
|
static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
CcwDevice *ccw_dev = CCW_DEVICE(dev);
|
||||||
|
|
||||||
if (!dev->sch->thinint_active) {
|
if (!ccw_dev->sch->thinint_active) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1115,7 +1125,8 @@ static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
||||||
bool with_irqfd = dev->sch->thinint_active && kvm_irqfds_enabled();
|
CcwDevice *ccw_dev = CCW_DEVICE(d);
|
||||||
|
bool with_irqfd = ccw_dev->sch->thinint_active && kvm_irqfds_enabled();
|
||||||
int r, n;
|
int r, n;
|
||||||
|
|
||||||
if (with_irqfd && assigned) {
|
if (with_irqfd && assigned) {
|
||||||
|
@ -1174,7 +1185,8 @@ static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
|
||||||
static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
|
static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
SubchDev *s = dev->sch;
|
CcwDevice *ccw_dev = CCW_DEVICE(d);
|
||||||
|
SubchDev *s = ccw_dev->sch;
|
||||||
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
|
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
|
||||||
|
|
||||||
subch_device_save(s, f);
|
subch_device_save(s, f);
|
||||||
|
@ -1208,7 +1220,8 @@ static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
|
||||||
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
|
static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
SubchDev *s = dev->sch;
|
CcwDevice *ccw_dev = CCW_DEVICE(d);
|
||||||
|
SubchDev *s = ccw_dev->sch;
|
||||||
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
|
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -1253,7 +1266,8 @@ static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
|
||||||
SubchDev *sch = dev->sch;
|
CcwDevice *ccw_dev = CCW_DEVICE(d);
|
||||||
|
SubchDev *sch = ccw_dev->sch;
|
||||||
int n = virtio_get_num_queues(vdev);
|
int n = virtio_get_num_queues(vdev);
|
||||||
|
|
||||||
if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) {
|
if (virtio_get_num_queues(vdev) > VIRTIO_CCW_QUEUE_MAX) {
|
||||||
|
@ -1297,7 +1311,7 @@ static void virtio_ccw_device_unplugged(DeviceState *d)
|
||||||
/**************** Virtio-ccw Bus Device Descriptions *******************/
|
/**************** Virtio-ccw Bus Device Descriptions *******************/
|
||||||
|
|
||||||
static Property virtio_ccw_net_properties[] = {
|
static Property virtio_ccw_net_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
@ -1326,7 +1340,7 @@ static const TypeInfo virtio_ccw_net = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Property virtio_ccw_blk_properties[] = {
|
static Property virtio_ccw_blk_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
@ -1355,7 +1369,7 @@ static const TypeInfo virtio_ccw_blk = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Property virtio_ccw_serial_properties[] = {
|
static Property virtio_ccw_serial_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
@ -1384,7 +1398,7 @@ static const TypeInfo virtio_ccw_serial = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Property virtio_ccw_balloon_properties[] = {
|
static Property virtio_ccw_balloon_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
@ -1413,7 +1427,7 @@ static const TypeInfo virtio_ccw_balloon = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static Property virtio_ccw_scsi_properties[] = {
|
static Property virtio_ccw_scsi_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
@ -1443,7 +1457,7 @@ static const TypeInfo virtio_ccw_scsi = {
|
||||||
|
|
||||||
#ifdef CONFIG_VHOST_SCSI
|
#ifdef CONFIG_VHOST_SCSI
|
||||||
static Property vhost_ccw_scsi_properties[] = {
|
static Property vhost_ccw_scsi_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
VIRTIO_CCW_MAX_REV),
|
VIRTIO_CCW_MAX_REV),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
@ -1481,7 +1495,7 @@ static void virtio_ccw_rng_instance_init(Object *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property virtio_ccw_rng_properties[] = {
|
static Property virtio_ccw_rng_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
@ -1525,32 +1539,20 @@ static int virtio_ccw_busdev_exit(DeviceState *dev)
|
||||||
return _info->exit(_dev);
|
return _info->exit(_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
|
static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
|
VirtioCcwDevice *_dev = to_virtio_ccw_dev_fast(dev);
|
||||||
SubchDev *sch = _dev->sch;
|
|
||||||
|
|
||||||
virtio_ccw_stop_ioeventfd(_dev);
|
virtio_ccw_stop_ioeventfd(_dev);
|
||||||
|
|
||||||
/*
|
|
||||||
* We should arrive here only for device_del, since we don't support
|
|
||||||
* direct hot(un)plug of channels, but only through virtio.
|
|
||||||
*/
|
|
||||||
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 virtio_ccw_device_class_init(ObjectClass *klass, void *data)
|
static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
CCWDeviceClass *k = CCW_DEVICE_CLASS(dc);
|
||||||
|
|
||||||
|
k->unplug = virtio_ccw_busdev_unplug;
|
||||||
dc->realize = virtio_ccw_busdev_realize;
|
dc->realize = virtio_ccw_busdev_realize;
|
||||||
dc->exit = virtio_ccw_busdev_exit;
|
dc->exit = virtio_ccw_busdev_exit;
|
||||||
dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
|
dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
|
||||||
|
@ -1558,7 +1560,7 @@ static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
static const TypeInfo virtio_ccw_device_info = {
|
static const TypeInfo virtio_ccw_device_info = {
|
||||||
.name = TYPE_VIRTIO_CCW_DEVICE,
|
.name = TYPE_VIRTIO_CCW_DEVICE,
|
||||||
.parent = TYPE_DEVICE,
|
.parent = TYPE_CCW_DEVICE,
|
||||||
.instance_size = sizeof(VirtioCcwDevice),
|
.instance_size = sizeof(VirtioCcwDevice),
|
||||||
.class_init = virtio_ccw_device_class_init,
|
.class_init = virtio_ccw_device_class_init,
|
||||||
.class_size = sizeof(VirtIOCCWDeviceClass),
|
.class_size = sizeof(VirtIOCCWDeviceClass),
|
||||||
|
@ -1610,7 +1612,7 @@ static const TypeInfo virtio_ccw_bus_info = {
|
||||||
|
|
||||||
#ifdef CONFIG_VIRTFS
|
#ifdef CONFIG_VIRTFS
|
||||||
static Property virtio_ccw_9p_properties[] = {
|
static Property virtio_ccw_9p_properties[] = {
|
||||||
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_CSS_DEV_ID("devno", VirtioCcwDevice, parent_obj.bus_id),
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include <hw/s390x/s390_flic.h>
|
#include <hw/s390x/s390_flic.h>
|
||||||
#include <hw/s390x/css.h>
|
#include <hw/s390x/css.h>
|
||||||
|
#include "ccw-device.h"
|
||||||
|
#include "hw/s390x/css-bridge.h"
|
||||||
|
|
||||||
#define VIRTIO_CCW_CU_TYPE 0x3832
|
#define VIRTIO_CCW_CU_TYPE 0x3832
|
||||||
#define VIRTIO_CCW_CHPID_TYPE 0x32
|
#define VIRTIO_CCW_CHPID_TYPE 0x32
|
||||||
|
@ -65,7 +67,7 @@ typedef struct VirtioBusClass VirtioCcwBusClass;
|
||||||
typedef struct VirtioCcwDevice VirtioCcwDevice;
|
typedef struct VirtioCcwDevice VirtioCcwDevice;
|
||||||
|
|
||||||
typedef struct VirtIOCCWDeviceClass {
|
typedef struct VirtIOCCWDeviceClass {
|
||||||
DeviceClass parent_class;
|
CCWDeviceClass parent_class;
|
||||||
void (*realize)(VirtioCcwDevice *dev, Error **errp);
|
void (*realize)(VirtioCcwDevice *dev, Error **errp);
|
||||||
int (*exit)(VirtioCcwDevice *dev);
|
int (*exit)(VirtioCcwDevice *dev);
|
||||||
} VirtIOCCWDeviceClass;
|
} VirtIOCCWDeviceClass;
|
||||||
|
@ -76,9 +78,7 @@ typedef struct VirtIOCCWDeviceClass {
|
||||||
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
|
#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
|
||||||
|
|
||||||
struct VirtioCcwDevice {
|
struct VirtioCcwDevice {
|
||||||
DeviceState parent_obj;
|
CcwDevice parent_obj;
|
||||||
SubchDev *sch;
|
|
||||||
CssDevId bus_id;
|
|
||||||
int revision;
|
int revision;
|
||||||
uint32_t max_rev;
|
uint32_t max_rev;
|
||||||
VirtioBusState bus;
|
VirtioBusState bus;
|
||||||
|
@ -101,9 +101,6 @@ static inline int virtio_ccw_rev_max(VirtioCcwDevice *dev)
|
||||||
return dev->max_rev;
|
return dev->max_rev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
|
|
||||||
DeviceState *dev, Error **errp);
|
|
||||||
|
|
||||||
/* virtio-scsi-ccw */
|
/* virtio-scsi-ccw */
|
||||||
|
|
||||||
#define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw"
|
#define TYPE_VIRTIO_SCSI_CCW "virtio-scsi-ccw"
|
||||||
|
|
Loading…
Reference in New Issue