@@ -390,6 +390,10 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
qdev_prop_set_vlan(dev, "vlan", nd->vlan);
if (nd->netdev)
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
+ if (nd->nvectors != NIC_NVECTORS_UNSPECIFIED &&
+ qdev_prop_exists(dev, "vectors")) {
+ qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
+ }
}
static int next_block_unit[IF_COUNT];
@@ -77,13 +77,13 @@ static void syborg_init(ram_addr_t ram_size,
sysbus_create_simple("syborg,serial", 0xC0008000, pic[7]);
sysbus_create_simple("syborg,serial", 0xC0009000, pic[8]);
- if (nd_table[0].vlan) {
+ if (nd_table[0].vlan || nd_table[0].netdev) {
DeviceState *dev;
SysBusDevice *s;
qemu_check_nic_model(&nd_table[0], "virtio");
dev = qdev_create(NULL, "syborg,virtio-net");
- dev->nd = &nd_table[0];
+ qdev_set_nic_properties(dev, &nd_table[0]);
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xc000c000);
@@ -65,6 +65,7 @@ typedef struct {
qemu_irq irq;
uint32_t int_enable;
uint32_t id;
+ NICConf nic;
} SyborgVirtIOProxy;
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
@@ -273,14 +274,23 @@ static int syborg_virtio_net_init(SysBusDevice *dev)
VirtIODevice *vdev;
SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
- vdev = virtio_net_init(&dev->qdev);
+ vdev = virtio_net_init(&dev->qdev, &proxy->nic);
return syborg_virtio_init(proxy, vdev);
}
+static SysBusDeviceInfo syborg_virtio_net_info = {
+ .init = syborg_virtio_net_init,
+ .qdev.name = "syborg,virtio-net",
+ .qdev.size = sizeof(SyborgVirtIOProxy),
+ .qdev.props = (Property[]) {
+ DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
static void syborg_virtio_register_devices(void)
{
- sysbus_register_dev("syborg,virtio-net", sizeof(SyborgVirtIOProxy),
- syborg_virtio_net_init);
+ sysbus_register_withprop(&syborg_virtio_net_info);
}
device_init(syborg_virtio_register_devices)
@@ -700,20 +700,10 @@ static void virtio_net_cleanup(VLANClientState *vc)
{
VirtIONet *n = vc->opaque;
- qemu_purge_queued_packets(vc);
-
- unregister_savevm("virtio-net", n);
-
- qemu_free(n->mac_table.macs);
- qemu_free(n->vlans);
-
- qemu_del_timer(n->tx_timer);
- qemu_free_timer(n->tx_timer);
-
- virtio_cleanup(&n->vdev);
+ n->vc = NULL;
}
-VirtIODevice *virtio_net_init(DeviceState *dev)
+VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
{
VirtIONet *n;
static int virtio_net_id;
@@ -731,15 +721,16 @@ VirtIODevice *virtio_net_init(DeviceState *dev)
n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
n->ctrl_vq = virtio_add_queue(&n->vdev, 64, virtio_net_handle_ctrl);
- qdev_get_macaddr(dev, n->mac);
+ qemu_macaddr_default_if_unset(&conf->macaddr);
n->status = VIRTIO_NET_S_LINK_UP;
- n->vc = qdev_get_vlan_client(dev,
+ n->vc = qemu_new_vlan_client(conf->vlan, conf->peer,
+ dev->info->name, dev->id,
virtio_net_can_receive,
virtio_net_receive, NULL,
virtio_net_cleanup, n);
n->vc->link_status_changed = virtio_net_set_link_status;
- qemu_format_nic_info_str(n->vc, n->mac);
+ qemu_format_nic_info_str(n->vc, conf->macaddr.a);
n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
n->tx_timer_active = 0;
@@ -749,13 +740,27 @@ VirtIODevice *virtio_net_init(DeviceState *dev)
n->mac_table.macs = qemu_mallocz(MAC_TABLE_ENTRIES * ETH_ALEN);
n->vlans = qemu_mallocz(MAX_VLAN >> 3);
- if (dev->nd->nvectors == NIC_NVECTORS_UNSPECIFIED)
- n->vdev.nvectors = 3;
- else
- n->vdev.nvectors = dev->nd->nvectors;
register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
virtio_net_save, virtio_net_load, n);
return &n->vdev;
}
+
+void virtio_net_exit(VirtIODevice *vdev)
+{
+ VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
+
+ qemu_purge_queued_packets(n->vc);
+
+ unregister_savevm("virtio-net", n);
+
+ qemu_free(n->mac_table.macs);
+ qemu_free(n->vlans);
+
+ qemu_del_timer(n->tx_timer);
+ qemu_free_timer(n->tx_timer);
+
+ virtio_cleanup(&n->vdev);
+ qemu_del_vlan_client(n->vc);
+}
@@ -20,6 +20,7 @@
#include "sysemu.h"
#include "msix.h"
#include "net.h"
+#include "loader.h"
/* from Linux's linux/virtio_pci.h */
@@ -90,6 +91,7 @@ typedef struct {
uint32_t class_code;
uint32_t nvectors;
DriveInfo *dinfo;
+ NICConf nic;
} VirtIOPCIProxy;
/* virtio device */
@@ -493,14 +495,9 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
VirtIODevice *vdev;
- vdev = virtio_net_init(&pci_dev->qdev);
-
- /* set nvectors from property, unless the user specified something
- * via -net nic,model=virtio,vectors=n command line option */
- if (pci_dev->qdev.nd->nvectors == NIC_NVECTORS_UNSPECIFIED)
- if (proxy->nvectors != NIC_NVECTORS_UNSPECIFIED)
- vdev->nvectors = proxy->nvectors;
+ vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic);
+ vdev->nvectors = proxy->nvectors;
virtio_init_pci(proxy, vdev,
PCI_VENDOR_ID_REDHAT_QUMRANET,
PCI_DEVICE_ID_VIRTIO_NET,
@@ -509,9 +506,25 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
/* make the actual value visible */
proxy->nvectors = vdev->nvectors;
+
+ if (!pci_dev->qdev.hotplugged) {
+ static int loaded = 0;
+ if (!loaded) {
+ rom_add_option("pxe-virtio.bin");
+ loaded = 1;
+ }
+ }
return 0;
}
+static int virtio_net_exit_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+ virtio_net_exit(proxy->vdev);
+ return virtio_exit_pci(pci_dev);
+}
+
static int virtio_balloon_init_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -543,10 +556,10 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.name = "virtio-net-pci",
.qdev.size = sizeof(VirtIOPCIProxy),
.init = virtio_net_init_pci,
- .exit = virtio_exit_pci,
+ .exit = virtio_net_exit_pci,
.qdev.props = (Property[]) {
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
- NIC_NVECTORS_UNSPECIFIED),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+ DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
DEFINE_PROP_END_OF_LIST(),
},
.qdev.reset = virtio_pci_reset,
@@ -15,6 +15,7 @@
#define _QEMU_VIRTIO_H
#include "hw.h"
+#include "net.h"
#include "qdev.h"
#include "sysemu.h"
@@ -163,8 +164,10 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
/* Base devices. */
VirtIODevice *virtio_blk_init(DeviceState *dev, DriveInfo *dinfo);
-VirtIODevice *virtio_net_init(DeviceState *dev);
+VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf);
VirtIODevice *virtio_console_init(DeviceState *dev);
VirtIODevice *virtio_balloon_init(DeviceState *dev);
+void virtio_net_exit(VirtIODevice *vdev);
+
#endif
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> --- hw/qdev.c | 4 ++++ hw/syborg.c | 4 ++-- hw/syborg_virtio.c | 16 +++++++++++++--- hw/virtio-net.c | 43 ++++++++++++++++++++++++------------------- hw/virtio-pci.c | 33 +++++++++++++++++++++++---------- hw/virtio.h | 5 ++++- 6 files changed, 70 insertions(+), 35 deletions(-)