diff --git a/hw/qdev.c b/hw/qdev.c index b32dbfc1fa..e81d6621c1 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -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]; diff --git a/hw/syborg.c b/hw/syborg.c index 2aec7691f4..2d08cb2492 100644 --- a/hw/syborg.c +++ b/hw/syborg.c @@ -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); diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c index c1faf3d1a0..6cf5a15c2c 100644 --- a/hw/syborg_virtio.c +++ b/hw/syborg_virtio.c @@ -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) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 218f985037..0a8d2aa859 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -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(NET_CLIENT_TYPE_NIC, conf->vlan, conf->peer, + dev->info->name, dev->id, virtio_net_can_receive, - virtio_net_receive, NULL, + virtio_net_receive, NULL, 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); +} diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index e07a2a77e2..1665b59baa 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -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, diff --git a/hw/virtio.h b/hw/virtio.h index 0f9be7d106..15ad910768 100644 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -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