diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/core/irq.c | 8 | ||||
-rw-r--r-- | hw/core/qdev.c | 70 | ||||
-rw-r--r-- | hw/core/sysbus.c | 20 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-bus.c | 6 | ||||
-rw-r--r-- | hw/s390x/virtio-ccw.c | 6 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi-dataplane.c | 102 | ||||
-rw-r--r-- | hw/scsi/virtio-scsi.c | 31 | ||||
-rw-r--r-- | hw/usb/hcd-uhci.c | 3 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 15 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 7 |
10 files changed, 198 insertions, 70 deletions
diff --git a/hw/core/irq.c b/hw/core/irq.c index cffced040f..8a62a36d5e 100644 --- a/hw/core/irq.c +++ b/hw/core/irq.c @@ -140,16 +140,10 @@ void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n) for (i = 0; i < n; i++) { *old_irqs[i] = *gpio_in[i]; gpio_in[i]->handler = handler; - gpio_in[i]->opaque = old_irqs; + gpio_in[i]->opaque = &old_irqs[i]; } } -void qemu_irq_intercept_out(qemu_irq **gpio_out, qemu_irq_handler handler, int n) -{ - qemu_irq *old_irqs = *gpio_out; - *gpio_out = qemu_allocate_irqs(handler, old_irqs, n); -} - static const TypeInfo irq_type_info = { .name = TYPE_IRQ, .parent = TYPE_OBJECT, diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 9357aba455..b3d519645a 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -404,9 +404,7 @@ void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins, char *propname = g_strdup_printf("%s[*]", name ? name : "unnamed-gpio-out"); assert(gpio_list->num_in == 0 || !name); - assert(gpio_list->num_out == 0); - gpio_list->num_out = n; - gpio_list->out = pins; + gpio_list->num_out += n; for (i = 0; i < n; ++i) { memset(&pins[i], 0, sizeof(*pins)); @@ -440,10 +438,44 @@ qemu_irq qdev_get_gpio_in(DeviceState *dev, int n) void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n, qemu_irq pin) { - NamedGPIOList *gpio_list = qdev_get_named_gpio_list(dev, name); + char *propname = g_strdup_printf("%s[%d]", + name ? name : "unnamed-gpio-out", n); + if (pin) { + /* We need a name for object_property_set_link to work. If the + * object has a parent, object_property_add_child will come back + * with an error without doing anything. If it has none, it will + * never fail. So we can just call it with a NULL Error pointer. + */ + object_property_add_child(qdev_get_machine(), "non-qdev-gpio[*]", + OBJECT(pin), NULL); + } + object_property_set_link(OBJECT(dev), OBJECT(pin), propname, &error_abort); + g_free(propname); +} + +/* disconnect a GPIO ouput, returning the disconnected input (if any) */ + +static qemu_irq qdev_disconnect_gpio_out_named(DeviceState *dev, + const char *name, int n) +{ + char *propname = g_strdup_printf("%s[%d]", + name ? name : "unnamed-gpio-out", n); + + qemu_irq ret = (qemu_irq)object_property_get_link(OBJECT(dev), propname, + NULL); + if (ret) { + object_property_set_link(OBJECT(dev), NULL, propname, NULL); + } + g_free(propname); + return ret; +} - assert(n >= 0 && n < gpio_list->num_out); - gpio_list->out[n] = pin; +qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt, + const char *name, int n) +{ + qemu_irq disconnected = qdev_disconnect_gpio_out_named(dev, name, n); + qdev_connect_gpio_out_named(dev, name, n, icpt); + return disconnected; } void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) @@ -451,6 +483,32 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin) qdev_connect_gpio_out_named(dev, NULL, n, pin); } +void qdev_pass_gpios(DeviceState *dev, DeviceState *container, + const char *name) +{ + int i; + NamedGPIOList *ngl = qdev_get_named_gpio_list(dev, name); + + for (i = 0; i < ngl->num_in; i++) { + const char *nm = ngl->name ? ngl->name : "unnamed-gpio-in"; + char *propname = g_strdup_printf("%s[%d]", nm, i); + + object_property_add_alias(OBJECT(container), propname, + OBJECT(dev), propname, + &error_abort); + } + for (i = 0; i < ngl->num_out; i++) { + const char *nm = ngl->name ? ngl->name : "unnamed-gpio-out"; + char *propname = g_strdup_printf("%s[%d]", nm, i); + + object_property_add_alias(OBJECT(container), propname, + OBJECT(dev), propname, + &error_abort); + } + QLIST_REMOVE(ngl, node); + QLIST_INSERT_HEAD(&container->gpios, ngl, node); +} + BusState *qdev_get_child_bus(DeviceState *dev, const char *name) { BusState *bus; diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 414e2a1921..e55c3c1d6d 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -41,11 +41,7 @@ static const TypeInfo system_bus_info = { void sysbus_connect_irq(SysBusDevice *dev, int n, qemu_irq irq) { - assert(n >= 0 && n < dev->num_irq); - dev->irqs[n] = NULL; - if (dev->irqp[n]) { - *dev->irqp[n] = irq; - } + qdev_connect_gpio_out_named(DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ, n, irq); } static void sysbus_mmio_map_common(SysBusDevice *dev, int n, hwaddr addr, @@ -89,22 +85,13 @@ void sysbus_mmio_map_overlap(SysBusDevice *dev, int n, hwaddr addr, /* Request an IRQ source. The actual IRQ object may be populated later. */ void sysbus_init_irq(SysBusDevice *dev, qemu_irq *p) { - int n; - - assert(dev->num_irq < QDEV_MAX_IRQ); - n = dev->num_irq++; - dev->irqp[n] = p; + qdev_init_gpio_out_named(DEVICE(dev), p, SYSBUS_DEVICE_GPIO_IRQ, 1); } /* Pass IRQs from a target device. */ void sysbus_pass_irq(SysBusDevice *dev, SysBusDevice *target) { - int i; - assert(dev->num_irq == 0); - dev->num_irq = target->num_irq; - for (i = 0; i < dev->num_irq; i++) { - dev->irqp[i] = target->irqp[i]; - } + qdev_pass_gpios(DEVICE(target), DEVICE(dev), SYSBUS_DEVICE_GPIO_IRQ); } void sysbus_init_mmio(SysBusDevice *dev, MemoryRegion *memory) @@ -210,7 +197,6 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) hwaddr size; int i; - monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq); for (i = 0; i < s->num_mmio; i++) { size = memory_region_size(s->mmio[i].memory); monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n", diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c index 2059874ae3..39dc2011b9 100644 --- a/hw/s390x/s390-virtio-bus.c +++ b/hw/s390x/s390-virtio-bus.c @@ -311,10 +311,8 @@ static void s390_virtio_rng_instance_init(Object *obj) virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->vdev.conf.rng, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); + object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), + "rng", &error_abort); } static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq) diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index 1c0d91321a..ea236c9b01 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1544,10 +1544,8 @@ static void virtio_ccw_rng_instance_init(Object *obj) virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->vdev.conf.rng, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); + object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), + "rng", &error_abort); } static Property virtio_ccw_rng_properties[] = { diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 48dcfd2852..3097d544b4 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -46,11 +46,15 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); VirtIOSCSIVring *r = g_slice_new(VirtIOSCSIVring); + int rc; /* Set up virtqueue notify */ - if (k->set_host_notifier(qbus->parent, n, true) != 0) { - fprintf(stderr, "virtio-scsi: Failed to set host notifier\n"); - exit(1); + rc = k->set_host_notifier(qbus->parent, n, true); + if (rc != 0) { + fprintf(stderr, "virtio-scsi: Failed to set host notifier (%d)\n", + rc); + s->dataplane_fenced = true; + return NULL; } r->host_notifier = *virtio_queue_get_host_notifier(vq); r->guest_notifier = *virtio_queue_get_guest_notifier(vq); @@ -60,9 +64,15 @@ static VirtIOSCSIVring *virtio_scsi_vring_init(VirtIOSCSI *s, if (!vring_setup(&r->vring, VIRTIO_DEVICE(s), n)) { fprintf(stderr, "virtio-scsi: VRing setup failed\n"); - exit(1); + goto fail_vring; } return r; + +fail_vring: + aio_set_event_notifier(s->ctx, &r->host_notifier, NULL); + k->set_host_notifier(qbus->parent, n, false); + g_slice_free(VirtIOSCSIVring, r); + return NULL; } VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s, @@ -138,6 +148,46 @@ static void virtio_scsi_iothread_handle_cmd(EventNotifier *notifier) } } +/* assumes s->ctx held */ +static void virtio_scsi_clear_aio(VirtIOSCSI *s) +{ + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); + int i; + + if (s->ctrl_vring) { + aio_set_event_notifier(s->ctx, &s->ctrl_vring->host_notifier, NULL); + } + if (s->event_vring) { + aio_set_event_notifier(s->ctx, &s->event_vring->host_notifier, NULL); + } + if (s->cmd_vrings) { + for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { + aio_set_event_notifier(s->ctx, &s->cmd_vrings[i]->host_notifier, NULL); + } + } +} + +static void virtio_scsi_vring_teardown(VirtIOSCSI *s) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(s); + VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); + int i; + + if (s->ctrl_vring) { + vring_teardown(&s->ctrl_vring->vring, vdev, 0); + } + if (s->event_vring) { + vring_teardown(&s->event_vring->vring, vdev, 1); + } + if (s->cmd_vrings) { + for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { + vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + i); + } + free(s->cmd_vrings); + s->cmd_vrings = NULL; + } +} + /* Context: QEMU global mutex held */ void virtio_scsi_dataplane_start(VirtIOSCSI *s) { @@ -149,38 +199,62 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s) if (s->dataplane_started || s->dataplane_starting || + s->dataplane_fenced || s->ctx != iothread_get_aio_context(vs->conf.iothread)) { return; } s->dataplane_starting = true; + assert(!s->blocker); + error_setg(&s->blocker, "block device is in use by data plane"); /* Set up guest notifier (irq) */ rc = k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, true); if (rc != 0) { - fprintf(stderr, "virtio-scsi: Failed to set guest notifiers, " - "ensure -enable-kvm is set\n"); - exit(1); + fprintf(stderr, "virtio-scsi: Failed to set guest notifiers (%d), " + "ensure -enable-kvm is set\n", rc); + s->dataplane_fenced = true; + goto fail_guest_notifiers; } aio_context_acquire(s->ctx); s->ctrl_vring = virtio_scsi_vring_init(s, vs->ctrl_vq, virtio_scsi_iothread_handle_ctrl, 0); + if (!s->ctrl_vring) { + goto fail_vrings; + } s->event_vring = virtio_scsi_vring_init(s, vs->event_vq, virtio_scsi_iothread_handle_event, 1); + if (!s->event_vring) { + goto fail_vrings; + } s->cmd_vrings = g_malloc0(sizeof(VirtIOSCSIVring) * vs->conf.num_queues); for (i = 0; i < vs->conf.num_queues; i++) { s->cmd_vrings[i] = virtio_scsi_vring_init(s, vs->cmd_vqs[i], virtio_scsi_iothread_handle_cmd, i + 2); + if (!s->cmd_vrings[i]) { + goto fail_vrings; + } } aio_context_release(s->ctx); s->dataplane_starting = false; s->dataplane_started = true; + +fail_vrings: + virtio_scsi_clear_aio(s); + aio_context_release(s->ctx); + virtio_scsi_vring_teardown(s); + for (i = 0; i < vs->conf.num_queues + 2; i++) { + k->set_host_notifier(qbus->parent, i, false); + } + k->set_guest_notifiers(qbus->parent, vs->conf.num_queues + 2, false); +fail_guest_notifiers: + s->dataplane_starting = false; } /* Context: QEMU global mutex held */ @@ -188,13 +262,19 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) { BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); - VirtIODevice *vdev = VIRTIO_DEVICE(s); VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(s); int i; + /* Better luck next time. */ + if (s->dataplane_fenced) { + s->dataplane_fenced = false; + return; + } if (!s->dataplane_started || s->dataplane_stopping) { return; } + error_free(s->blocker); + s->blocker = NULL; s->dataplane_stopping = true; assert(s->ctx == iothread_get_aio_context(vs->conf.iothread)); @@ -213,11 +293,7 @@ void virtio_scsi_dataplane_stop(VirtIOSCSI *s) /* Sync vring state back to virtqueue so that non-dataplane request * processing can continue when we disable the host notifier below. */ - vring_teardown(&s->ctrl_vring->vring, vdev, 0); - vring_teardown(&s->event_vring->vring, vdev, 1); - for (i = 0; i < vs->conf.num_queues; i++) { - vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + i); - } + virtio_scsi_vring_teardown(s); for (i = 0; i < vs->conf.num_queues + 2; i++) { k->set_host_notifier(qbus->parent, i, false); diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index a1725b8f48..7d40eccb0c 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -369,7 +369,7 @@ fail: void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req) { VirtIODevice *vdev = (VirtIODevice *)s; - int type; + uint32_t type; int r = 0; if (iov_to_buf(req->elem.out_sg, req->elem.out_num, 0, @@ -378,8 +378,8 @@ void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req) return; } - virtio_tswap32s(vdev, &req->req.tmf.type); - if (req->req.tmf.type == VIRTIO_SCSI_T_TMF) { + virtio_tswap32s(vdev, &type); + if (type == VIRTIO_SCSI_T_TMF) { if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlTMFReq), sizeof(VirtIOSCSICtrlTMFResp)) < 0) { virtio_scsi_bad_req(); @@ -387,8 +387,8 @@ void virtio_scsi_handle_ctrl_req(VirtIOSCSI *s, VirtIOSCSIReq *req) r = virtio_scsi_do_tmf(s, req); } - } else if (req->req.tmf.type == VIRTIO_SCSI_T_AN_QUERY || - req->req.tmf.type == VIRTIO_SCSI_T_AN_SUBSCRIBE) { + } else if (type == VIRTIO_SCSI_T_AN_QUERY || + type == VIRTIO_SCSI_T_AN_SUBSCRIBE) { if (virtio_scsi_parse_req(req, sizeof(VirtIOSCSICtrlANReq), sizeof(VirtIOSCSICtrlANResp)) < 0) { virtio_scsi_bad_req(); @@ -448,7 +448,7 @@ static void virtio_scsi_command_complete(SCSIRequest *r, uint32_t status, sense_len = scsi_req_get_sense(r, sense, sizeof(sense)); sense_len = MIN(sense_len, req->resp_iov.size - sizeof(req->resp.cmd)); qemu_iovec_from_buf(&req->resp_iov, sizeof(req->resp.cmd), - &req->resp, sense_len); + sense, sense_len); req->resp.cmd.sense_len = virtio_tswap32(vdev, sense_len); } virtio_scsi_complete_cmd_req(req); @@ -742,9 +742,18 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + SCSIDevice *sd = SCSI_DEVICE(dev); + + if (s->ctx && !s->dataplane_disabled) { + if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { + return; + } + blk_op_block_all(sd->conf.blk, s->blocker); + } if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { - virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), + virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_RESCAN); } @@ -754,12 +763,18 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(hotplug_dev); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + SCSIDevice *sd = SCSI_DEVICE(dev); if ((vdev->guest_features >> VIRTIO_SCSI_F_HOTPLUG) & 1) { - virtio_scsi_push_event(VIRTIO_SCSI(hotplug_dev), SCSI_DEVICE(dev), + virtio_scsi_push_event(s, sd, VIRTIO_SCSI_T_TRANSPORT_RESET, VIRTIO_SCSI_EVT_RESET_REMOVED); } + + if (s->ctx) { + blk_op_unblock_all(sd->conf.blk, s->blocker); + } qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); } diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 5b88f3070f..4a4215d332 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -35,9 +35,6 @@ #include "trace.h" #include "qemu/main-loop.h" -//#define DEBUG -//#define DEBUG_DUMP_DATA - #define FRAME_TIMER_FREQ 1000 #define FRAME_MAX_LOOPS 256 diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index a27c9d37fa..2930b72c1d 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -459,6 +459,7 @@ struct XHCIState { uint32_t numintrs; uint32_t numslots; uint32_t flags; + uint32_t max_pstreams_mask; /* Operational Registers */ uint32_t usbcmd; @@ -500,6 +501,7 @@ enum xhci_flags { XHCI_FLAG_USE_MSI_X, XHCI_FLAG_SS_FIRST, XHCI_FLAG_FORCE_PCIE_ENDCAP, + XHCI_FLAG_ENABLE_STREAMS, }; static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, @@ -1384,7 +1386,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx, epctx->pctx = pctx; epctx->max_psize = ctx[1]>>16; epctx->max_psize *= 1+((ctx[1]>>8)&0xff); - epctx->max_pstreams = (ctx[0] >> 10) & 0xf; + epctx->max_pstreams = (ctx[0] >> 10) & epctx->xhci->max_pstreams_mask; epctx->lsa = (ctx[0] >> 15) & 1; if (epctx->max_pstreams) { xhci_alloc_streams(epctx, dequeue); @@ -2956,9 +2958,9 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) break; case 0x10: /* HCCPARAMS */ if (sizeof(dma_addr_t) == 4) { - ret = 0x00087000; + ret = 0x00080000 | (xhci->max_pstreams_mask << 12); } else { - ret = 0x00087001; + ret = 0x00080001 | (xhci->max_pstreams_mask << 12); } break; case 0x14: /* DBOFF */ @@ -3590,6 +3592,11 @@ static int usb_xhci_initfn(struct PCIDevice *dev) if (xhci->numslots < 1) { xhci->numslots = 1; } + if (xhci_get_flag(xhci, XHCI_FLAG_ENABLE_STREAMS)) { + xhci->max_pstreams_mask = 7; /* == 256 primary streams */ + } else { + xhci->max_pstreams_mask = 0; + } xhci->mfwrap_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, xhci_mfwrap_timer, xhci); @@ -3853,6 +3860,8 @@ static Property xhci_properties[] = { XHCIState, flags, XHCI_FLAG_SS_FIRST, true), DEFINE_PROP_BIT("force-pcie-endcap", XHCIState, flags, XHCI_FLAG_FORCE_PCIE_ENDCAP, false), + DEFINE_PROP_BIT("streams", XHCIState, flags, + XHCI_FLAG_ENABLE_STREAMS, true), DEFINE_PROP_UINT32("intrs", XHCIState, numintrs, MAXINTRS), DEFINE_PROP_UINT32("slots", XHCIState, numslots, MAXSLOTS), DEFINE_PROP_UINT32("p2", XHCIState, numports_2, 4), diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 542fb9e279..e490adeb80 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1525,11 +1525,8 @@ static void virtio_rng_initfn(Object *obj) virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_RNG); - object_property_add_link(obj, "rng", TYPE_RNG_BACKEND, - (Object **)&dev->vdev.conf.rng, - qdev_prop_allow_set_link_before_realize, - OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); - + object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), "rng", + &error_abort); } static const TypeInfo virtio_rng_pci_info = { |