summaryrefslogtreecommitdiff
path: root/hw/net
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-02-08 11:25:31 +0000
committerPeter Maydell <peter.maydell@linaro.org>2016-02-08 11:25:31 +0000
commitbdad0f3977ee38f681453f602ddec9f4e24b03f9 (patch)
tree236ceead1b8de76a588474ab3b2d3e48a2f1c1a8 /hw/net
parentee8e8f92a730afc17ab8be6e86df6b9a23b8ebc6 (diff)
parenta407644079c8639002e7ea635d851953b10a38c3 (diff)
downloadqemu-bdad0f3977ee38f681453f602ddec9f4e24b03f9.tar.gz
qemu-bdad0f3977ee38f681453f602ddec9f4e24b03f9.tar.bz2
qemu-bdad0f3977ee38f681453f602ddec9f4e24b03f9.zip
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.c23
-rw-r--r--hw/net/virtio-net.c69
2 files changed, 54 insertions, 38 deletions
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 0bd5131fdb..3940a04b65 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 fde8dd3157..de696e8dd0 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;