diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-02-08 11:25:31 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-02-08 11:25:31 +0000 |
commit | bdad0f3977ee38f681453f602ddec9f4e24b03f9 (patch) | |
tree | 236ceead1b8de76a588474ab3b2d3e48a2f1c1a8 /hw/net | |
parent | ee8e8f92a730afc17ab8be6e86df6b9a23b8ebc6 (diff) | |
parent | a407644079c8639002e7ea635d851953b10a38c3 (diff) | |
download | qemu-bdad0f3977ee38f681453f602ddec9f4e24b03f9.zip qemu-bdad0f3977ee38f681453f602ddec9f4e24b03f9.tar.gz qemu-bdad0f3977ee38f681453f602ddec9f4e24b03f9.tar.bz2 |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc and misc cleanups and fixes, virtio optimizations
Included here:
Refactoring and bugfix patches in PC/ACPI.
New commands for ipmi.
Virtio optimizations.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Sat 06 Feb 2016 18:44:26 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
* remotes/mst/tags/for_upstream: (45 commits)
net: set endianness on all backend devices
fix MSI injection on Xen
intel_iommu: large page support
dimm: Correct type of MemoryHotplugState->base
pc: set the OEM fields in the RSDT and the FADT from the SLIC
acpi: add function to extract oem_id and oem_table_id from the user's SLIC
acpi: expose oem_id and oem_table_id in build_rsdt()
acpi: take oem_id in build_header(), optionally
pc: Eliminate PcGuestInfo struct
pc: Move APIC and NUMA data from PcGuestInfo to PCMachineState
pc: Move PcGuestInfo.fw_cfg to PCMachineState
pc: Remove PcGuestInfo.isapc_ram_fw field
pc: Remove RAM size fields from PcGuestInfo
pc: Remove compat fields from PcGuestInfo
acpi: Don't save PcGuestInfo on AcpiBuildState
acpi: Remove guest_info parameters from functions
pc: Simplify xen_load_linux() signature
pc: Simplify pc_memory_init() signature
pc: Eliminate struct PcGuestInfoState
pc: Move PcGuestInfo declaration to top of file
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/net')
-rw-r--r-- | hw/net/vhost_net.c | 23 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 69 |
2 files changed, 54 insertions, 38 deletions
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 0bd5131..3940a04 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -298,21 +298,19 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); - int r, e, i; + int r, e, i, j; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); - r = -ENOSYS; - goto err; + return -ENOSYS; } - r = vhost_net_set_vnet_endian(dev, ncs[0].peer, true); - if (r < 0) { - goto err; - } - - for (i = 0; i < total_queues; i++) { - vhost_net_set_vq_index(get_vhost_net(ncs[i].peer), i * 2); + for (j = 0; j < total_queues; j++) { + r = vhost_net_set_vnet_endian(dev, ncs[j].peer, true); + if (r < 0) { + goto err_endian; + } + vhost_net_set_vq_index(get_vhost_net(ncs[j].peer), j * 2); } r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); @@ -341,8 +339,9 @@ err_start: fflush(stderr); } err_endian: - vhost_net_set_vnet_endian(dev, ncs[0].peer, false); -err: + while (--j >= 0) { + vhost_net_set_vnet_endian(dev, ncs[j].peer, false); + } return r; } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index fde8dd3..de696e8 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -819,20 +819,24 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) VirtIONet *n = VIRTIO_NET(vdev); struct virtio_net_ctrl_hdr ctrl; virtio_net_ctrl_ack status = VIRTIO_NET_ERR; - VirtQueueElement elem; + VirtQueueElement *elem; size_t s; struct iovec *iov, *iov2; unsigned int iov_cnt; - while (virtqueue_pop(vq, &elem)) { - if (iov_size(elem.in_sg, elem.in_num) < sizeof(status) || - iov_size(elem.out_sg, elem.out_num) < sizeof(ctrl)) { + for (;;) { + elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } + if (iov_size(elem->in_sg, elem->in_num) < sizeof(status) || + iov_size(elem->out_sg, elem->out_num) < sizeof(ctrl)) { error_report("virtio-net ctrl missing headers"); exit(1); } - iov_cnt = elem.out_num; - iov2 = iov = g_memdup(elem.out_sg, sizeof(struct iovec) * elem.out_num); + iov_cnt = elem->out_num; + iov2 = iov = g_memdup(elem->out_sg, sizeof(struct iovec) * elem->out_num); s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl)); iov_discard_front(&iov, &iov_cnt, sizeof(ctrl)); if (s != sizeof(ctrl)) { @@ -851,12 +855,13 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt); } - s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status)); + s = iov_from_buf(elem->in_sg, elem->in_num, 0, &status, sizeof(status)); assert(s == sizeof(status)); - virtqueue_push(vq, &elem, sizeof(status)); + virtqueue_push(vq, elem, sizeof(status)); virtio_notify(vdev, vq); g_free(iov2); + g_free(elem); } } @@ -1045,13 +1050,14 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t offset = i = 0; while (offset < size) { - VirtQueueElement elem; + VirtQueueElement *elem; int len, total; - const struct iovec *sg = elem.in_sg; + const struct iovec *sg; total = 0; - if (virtqueue_pop(q->rx_vq, &elem) == 0) { + elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement)); + if (!elem) { if (i == 0) return -1; error_report("virtio-net unexpected empty queue: " @@ -1064,21 +1070,22 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t exit(1); } - if (elem.in_num < 1) { + if (elem->in_num < 1) { error_report("virtio-net receive queue contains no in buffers"); exit(1); } + sg = elem->in_sg; if (i == 0) { assert(offset == 0); if (n->mergeable_rx_bufs) { mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg), - sg, elem.in_num, + sg, elem->in_num, offsetof(typeof(mhdr), num_buffers), sizeof(mhdr.num_buffers)); } - receive_header(n, sg, elem.in_num, buf, size); + receive_header(n, sg, elem->in_num, buf, size); offset = n->host_hdr_len; total += n->guest_hdr_len; guest_offset = n->guest_hdr_len; @@ -1087,7 +1094,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t } /* copy in packet. ugh */ - len = iov_from_buf(sg, elem.in_num, guest_offset, + len = iov_from_buf(sg, elem->in_num, guest_offset, buf + offset, size - offset); total += len; offset += len; @@ -1095,12 +1102,14 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t * must have consumed the complete packet. * Otherwise, drop it. */ if (!n->mergeable_rx_bufs && offset < size) { - virtqueue_discard(q->rx_vq, &elem, total); + virtqueue_discard(q->rx_vq, elem, total); + g_free(elem); return size; } /* signal other side */ - virtqueue_fill(q->rx_vq, &elem, total, i++); + virtqueue_fill(q->rx_vq, elem, total, i++); + g_free(elem); } if (mhdr_cnt) { @@ -1124,10 +1133,11 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len) VirtIONetQueue *q = virtio_net_get_subqueue(nc); VirtIODevice *vdev = VIRTIO_DEVICE(n); - virtqueue_push(q->tx_vq, &q->async_tx.elem, 0); + virtqueue_push(q->tx_vq, q->async_tx.elem, 0); virtio_notify(vdev, q->tx_vq); - q->async_tx.elem.out_num = 0; + g_free(q->async_tx.elem); + q->async_tx.elem = NULL; virtio_queue_set_notification(q->tx_vq, 1); virtio_net_flush_tx(q); @@ -1138,25 +1148,31 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) { VirtIONet *n = q->n; VirtIODevice *vdev = VIRTIO_DEVICE(n); - VirtQueueElement elem; + VirtQueueElement *elem; int32_t num_packets = 0; int queue_index = vq2q(virtio_get_queue_index(q->tx_vq)); if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { return num_packets; } - if (q->async_tx.elem.out_num) { + if (q->async_tx.elem) { virtio_queue_set_notification(q->tx_vq, 0); return num_packets; } - while (virtqueue_pop(q->tx_vq, &elem)) { + for (;;) { ssize_t ret; - unsigned int out_num = elem.out_num; - struct iovec *out_sg = &elem.out_sg[0]; - struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1]; + unsigned int out_num; + struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg; struct virtio_net_hdr_mrg_rxbuf mhdr; + elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement)); + if (!elem) { + break; + } + + out_num = elem->out_num; + out_sg = elem->out_sg; if (out_num < 1) { error_report("virtio-net header not in first element"); exit(1); @@ -1208,8 +1224,9 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) } drop: - virtqueue_push(q->tx_vq, &elem, 0); + virtqueue_push(q->tx_vq, elem, 0); virtio_notify(vdev, q->tx_vq); + g_free(elem); if (++num_packets >= n->tx_burst) { break; |