aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-03-16 10:53:47 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-03-16 10:53:47 +0000
commit6e31b3a5c34c6e5be7ef60773e607f189eaa15f3 (patch)
treed12963d6df1819264b349159e6ed49b41f9e3eb0 /hw
parent2615a5e433aeb812c300d3a48e1a88e1303e2339 (diff)
parentf2e8319d456724c3d8514d943dc4607e2f08e88a (diff)
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging
# gpg: Signature made Mon 15 Mar 2021 08:42:25 GMT # gpg: using RSA key EF04965B398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [marginal] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * remotes/jasowang/tags/net-pull-request: net: Do not fill legacy info_str for backends hmp: Use QAPI NetdevInfo in hmp_info_network net: Move NetClientState.info_str to dynamic allocations tests: Add tests for query-netdev command qapi: net: Add query-netdev command pvrdma: wean code off pvrdma_ring.h kernel header lan9118: switch to use qemu_receive_packet() for loopback cadence_gem: switch to use qemu_receive_packet() for loopback pcnet: switch to use qemu_receive_packet() for loopback rtl8139: switch to use qemu_receive_packet() for loopback tx_pkt: switch to use qemu_receive_packet_iov() for loopback sungem: switch to use qemu_receive_packet() for loopback msf2-mac: switch to use qemu_receive_packet() for loopback dp8393x: switch to use qemu_receive_packet() for loopback packet e1000: switch to use qemu_receive_packet() for loopback net: introduce qemu_receive_packet() e1000: fail early for evil descriptor net: validate that ids are well formed net: Fix build error when DEBUG_NET is on virtio-net: calculating proper msix vectors on init Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # hw/core/machine.c
Diffstat (limited to 'hw')
-rw-r--r--hw/core/machine.c1
-rw-r--r--hw/net/cadence_gem.c4
-rw-r--r--hw/net/dp8393x.c2
-rw-r--r--hw/net/e1000.c6
-rw-r--r--hw/net/lan9118.c2
-rw-r--r--hw/net/msf2-emac.c2
-rw-r--r--hw/net/net_tx_pkt.c2
-rw-r--r--hw/net/pcnet.c2
-rw-r--r--hw/net/rtl8139.c2
-rw-r--r--hw/net/sungem.c2
-rw-r--r--hw/net/xen_nic.c5
-rw-r--r--hw/rdma/vmw/pvrdma.h5
-rw-r--r--hw/rdma/vmw/pvrdma_cmd.c6
-rw-r--r--hw/rdma/vmw/pvrdma_dev_ring.c41
-rw-r--r--hw/rdma/vmw/pvrdma_dev_ring.h9
-rw-r--r--hw/rdma/vmw/pvrdma_main.c4
-rw-r--r--hw/virtio/virtio-net-pci.c10
17 files changed, 63 insertions, 42 deletions
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 4c1a4a4c32..257a664ea2 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -40,6 +40,7 @@ GlobalProperty hw_compat_5_2[] = {
{ "ICH9-LPC", "smm-compat", "on"},
{ "PIIX4_PM", "smm-compat", "on"},
{ "virtio-blk-device", "report-discard-granularity", "off" },
+ { "virtio-net-pci", "vectors", "3"},
};
const size_t hw_compat_5_2_len = G_N_ELEMENTS(hw_compat_5_2);
diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
index 9a4474a084..24b3a0ff66 100644
--- a/hw/net/cadence_gem.c
+++ b/hw/net/cadence_gem.c
@@ -1275,8 +1275,8 @@ static void gem_transmit(CadenceGEMState *s)
/* Send the packet somewhere */
if (s->phy_loop || (s->regs[GEM_NWCTRL] &
GEM_NWCTRL_LOCALLOOP)) {
- gem_receive(qemu_get_queue(s->nic), s->tx_packet,
- total_bytes);
+ qemu_receive_packet(qemu_get_queue(s->nic), s->tx_packet,
+ total_bytes);
} else {
qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet,
total_bytes);
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 205c0decc5..533a8304d0 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -506,7 +506,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
s->regs[SONIC_TCR] |= SONIC_TCR_CRSL;
if (nc->info->can_receive(nc)) {
s->loopback_packet = 1;
- nc->info->receive(nc, s->tx_buffer, tx_len);
+ qemu_receive_packet(nc, s->tx_buffer, tx_len);
}
} else {
/* Transmit packet */
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index d8da2f6528..4f75b44cfc 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -546,7 +546,7 @@ e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
NetClientState *nc = qemu_get_queue(s->nic);
if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
- nc->info->receive(nc, buf, size);
+ qemu_receive_packet(nc, buf, size);
} else {
qemu_send_packet(nc, buf, size);
}
@@ -670,6 +670,9 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
msh = tp->tso_props.hdr_len + tp->tso_props.mss;
do {
bytes = split_size;
+ if (tp->size >= msh) {
+ goto eop;
+ }
if (tp->size + bytes > msh)
bytes = msh - tp->size;
@@ -695,6 +698,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
tp->size += split_size;
}
+eop:
if (!(txd_lower & E1000_TXD_CMD_EOP))
return;
if (!(tp->cptse && tp->size < tp->tso_props.hdr_len)) {
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index abc796285a..6aff424cbe 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -680,7 +680,7 @@ static void do_tx_packet(lan9118_state *s)
/* FIXME: Honor TX disable, and allow queueing of packets. */
if (s->phy_control & 0x4000) {
/* This assumes the receive routine doesn't touch the VLANClient. */
- lan9118_receive(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
+ qemu_receive_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
} else {
qemu_send_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
}
diff --git a/hw/net/msf2-emac.c b/hw/net/msf2-emac.c
index 32ba9e8412..3e6206044f 100644
--- a/hw/net/msf2-emac.c
+++ b/hw/net/msf2-emac.c
@@ -158,7 +158,7 @@ static void msf2_dma_tx(MSF2EmacState *s)
* R_CFG1 bit 0 is set.
*/
if (s->regs[R_CFG1] & R_CFG1_LB_EN_MASK) {
- nc->info->receive(nc, buf, size);
+ qemu_receive_packet(nc, buf, size);
} else {
qemu_send_packet(nc, buf, size);
}
diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c
index da262edc3e..1f9aa59eca 100644
--- a/hw/net/net_tx_pkt.c
+++ b/hw/net/net_tx_pkt.c
@@ -553,7 +553,7 @@ static inline void net_tx_pkt_sendv(struct NetTxPkt *pkt,
NetClientState *nc, const struct iovec *iov, int iov_cnt)
{
if (pkt->is_loopback) {
- nc->info->receive_iov(nc, iov, iov_cnt);
+ qemu_receive_packet_iov(nc, iov, iov_cnt);
} else {
qemu_sendv_packet(nc, iov, iov_cnt);
}
diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
index f3f18d8598..dcd3fc4948 100644
--- a/hw/net/pcnet.c
+++ b/hw/net/pcnet.c
@@ -1250,7 +1250,7 @@ txagain:
if (BCR_SWSTYLE(s) == 1)
add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
- pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
+ qemu_receive_packet(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
s->looptest = 0;
} else {
if (s->nic) {
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 4675ac878e..90b4fc63ce 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -1795,7 +1795,7 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
}
DPRINTF("+++ transmit loopback mode\n");
- rtl8139_do_receive(qemu_get_queue(s->nic), buf, size, do_interrupt);
+ qemu_receive_packet(qemu_get_queue(s->nic), buf, size);
if (iov) {
g_free(buf2);
diff --git a/hw/net/sungem.c b/hw/net/sungem.c
index 33c3722df6..3684a4d733 100644
--- a/hw/net/sungem.c
+++ b/hw/net/sungem.c
@@ -306,7 +306,7 @@ static void sungem_send_packet(SunGEMState *s, const uint8_t *buf,
NetClientState *nc = qemu_get_queue(s->nic);
if (s->macregs[MAC_XIFCFG >> 2] & MAC_XIFCFG_LBCK) {
- nc->info->receive(nc, buf, size);
+ qemu_receive_packet(nc, buf, size);
} else {
qemu_send_packet(nc, buf, size);
}
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
index 5c815b4f0c..8431808ea0 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -296,9 +296,8 @@ static int net_init(struct XenLegacyDevice *xendev)
netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf,
"xen", NULL, netdev);
- snprintf(qemu_get_queue(netdev->nic)->info_str,
- sizeof(qemu_get_queue(netdev->nic)->info_str),
- "nic: xenbus vif macaddr=%s", netdev->mac);
+ qemu_get_queue(netdev->nic)->info_str = g_strdup_printf(
+ "nic: xenbus vif macaddr=%s", netdev->mac);
/* fill info */
xenstore_write_be_int(&netdev->xendev, "feature-rx-copy", 1);
diff --git a/hw/rdma/vmw/pvrdma.h b/hw/rdma/vmw/pvrdma.h
index 1d36a76f1e..d08965d3e2 100644
--- a/hw/rdma/vmw/pvrdma.h
+++ b/hw/rdma/vmw/pvrdma.h
@@ -26,7 +26,6 @@
#include "../rdma_backend_defs.h"
#include "../rdma_rm_defs.h"
-#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h"
#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h"
#include "pvrdma_dev_ring.h"
#include "qom/object.h"
@@ -64,10 +63,10 @@ typedef struct DSRInfo {
union pvrdma_cmd_req *req;
union pvrdma_cmd_resp *rsp;
- struct pvrdma_ring *async_ring_state;
+ PvrdmaRingState *async_ring_state;
PvrdmaRing async;
- struct pvrdma_ring *cq_ring_state;
+ PvrdmaRingState *cq_ring_state;
PvrdmaRing cq;
} DSRInfo;
diff --git a/hw/rdma/vmw/pvrdma_cmd.c b/hw/rdma/vmw/pvrdma_cmd.c
index 692125ac26..f59879e257 100644
--- a/hw/rdma/vmw/pvrdma_cmd.c
+++ b/hw/rdma/vmw/pvrdma_cmd.c
@@ -262,7 +262,7 @@ static int create_cq_ring(PCIDevice *pci_dev , PvrdmaRing **ring,
r = g_malloc(sizeof(*r));
*ring = r;
- r->ring_state = (struct pvrdma_ring *)
+ r->ring_state = (PvrdmaRingState *)
rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
if (!r->ring_state) {
@@ -398,7 +398,7 @@ static int create_qp_rings(PCIDevice *pci_dev, uint64_t pdir_dma,
*rings = sr;
/* Create send ring */
- sr->ring_state = (struct pvrdma_ring *)
+ sr->ring_state = (PvrdmaRingState *)
rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
if (!sr->ring_state) {
rdma_error_report("Failed to map to QP ring state");
@@ -639,7 +639,7 @@ static int create_srq_ring(PCIDevice *pci_dev, PvrdmaRing **ring,
r = g_malloc(sizeof(*r));
*ring = r;
- r->ring_state = (struct pvrdma_ring *)
+ r->ring_state = (PvrdmaRingState *)
rdma_pci_dma_map(pci_dev, tbl[0], TARGET_PAGE_SIZE);
if (!r->ring_state) {
rdma_error_report("Failed to map tp SRQ ring state");
diff --git a/hw/rdma/vmw/pvrdma_dev_ring.c b/hw/rdma/vmw/pvrdma_dev_ring.c
index f0bcde74b0..074ac59b84 100644
--- a/hw/rdma/vmw/pvrdma_dev_ring.c
+++ b/hw/rdma/vmw/pvrdma_dev_ring.c
@@ -22,11 +22,10 @@
#include "trace.h"
#include "../rdma_utils.h"
-#include "standard-headers/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h"
#include "pvrdma_dev_ring.h"
int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev,
- struct pvrdma_ring *ring_state, uint32_t max_elems,
+ PvrdmaRingState *ring_state, uint32_t max_elems,
size_t elem_sz, dma_addr_t *tbl, uint32_t npages)
{
int i;
@@ -73,48 +72,54 @@ out:
void *pvrdma_ring_next_elem_read(PvrdmaRing *ring)
{
- int e;
- unsigned int idx = 0, offset;
+ unsigned int idx, offset;
+ const uint32_t tail = qatomic_read(&ring->ring_state->prod_tail);
+ const uint32_t head = qatomic_read(&ring->ring_state->cons_head);
- e = pvrdma_idx_ring_has_data(ring->ring_state, ring->max_elems, &idx);
- if (e <= 0) {
+ if (tail & ~((ring->max_elems << 1) - 1) ||
+ head & ~((ring->max_elems << 1) - 1) ||
+ tail == head) {
trace_pvrdma_ring_next_elem_read_no_data(ring->name);
return NULL;
}
+ idx = head & (ring->max_elems - 1);
offset = idx * ring->elem_sz;
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
}
void pvrdma_ring_read_inc(PvrdmaRing *ring)
{
- pvrdma_idx_ring_inc(&ring->ring_state->cons_head, ring->max_elems);
+ uint32_t idx = qatomic_read(&ring->ring_state->cons_head);
+
+ idx = (idx + 1) & ((ring->max_elems << 1) - 1);
+ qatomic_set(&ring->ring_state->cons_head, idx);
}
void *pvrdma_ring_next_elem_write(PvrdmaRing *ring)
{
- int idx;
- unsigned int offset, tail;
+ unsigned int idx, offset;
+ const uint32_t tail = qatomic_read(&ring->ring_state->prod_tail);
+ const uint32_t head = qatomic_read(&ring->ring_state->cons_head);
- idx = pvrdma_idx_ring_has_space(ring->ring_state, ring->max_elems, &tail);
- if (idx <= 0) {
+ if (tail & ~((ring->max_elems << 1) - 1) ||
+ head & ~((ring->max_elems << 1) - 1) ||
+ tail == (head ^ ring->max_elems)) {
rdma_error_report("CQ is full");
return NULL;
}
- idx = pvrdma_idx(&ring->ring_state->prod_tail, ring->max_elems);
- if (idx < 0 || tail != idx) {
- rdma_error_report("Invalid idx %d", idx);
- return NULL;
- }
-
+ idx = tail & (ring->max_elems - 1);
offset = idx * ring->elem_sz;
return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % TARGET_PAGE_SIZE);
}
void pvrdma_ring_write_inc(PvrdmaRing *ring)
{
- pvrdma_idx_ring_inc(&ring->ring_state->prod_tail, ring->max_elems);
+ uint32_t idx = qatomic_read(&ring->ring_state->prod_tail);
+
+ idx = (idx + 1) & ((ring->max_elems << 1) - 1);
+ qatomic_set(&ring->ring_state->prod_tail, idx);
}
void pvrdma_ring_free(PvrdmaRing *ring)
diff --git a/hw/rdma/vmw/pvrdma_dev_ring.h b/hw/rdma/vmw/pvrdma_dev_ring.h
index 5f2a0cf9b9..d231588ce0 100644
--- a/hw/rdma/vmw/pvrdma_dev_ring.h
+++ b/hw/rdma/vmw/pvrdma_dev_ring.h
@@ -19,18 +19,23 @@
#define MAX_RING_NAME_SZ 32
+typedef struct PvrdmaRingState {
+ int prod_tail; /* producer tail */
+ int cons_head; /* consumer head */
+} PvrdmaRingState;
+
typedef struct PvrdmaRing {
char name[MAX_RING_NAME_SZ];
PCIDevice *dev;
uint32_t max_elems;
size_t elem_sz;
- struct pvrdma_ring *ring_state; /* used only for unmap */
+ PvrdmaRingState *ring_state; /* used only for unmap */
int npages;
void **pages;
} PvrdmaRing;
int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev,
- struct pvrdma_ring *ring_state, uint32_t max_elems,
+ PvrdmaRingState *ring_state, uint32_t max_elems,
size_t elem_sz, dma_addr_t *tbl, uint32_t npages);
void *pvrdma_ring_next_elem_read(PvrdmaRing *ring);
void pvrdma_ring_read_inc(PvrdmaRing *ring);
diff --git a/hw/rdma/vmw/pvrdma_main.c b/hw/rdma/vmw/pvrdma_main.c
index 8593570332..84ae8024fc 100644
--- a/hw/rdma/vmw/pvrdma_main.c
+++ b/hw/rdma/vmw/pvrdma_main.c
@@ -85,7 +85,7 @@ static void free_dev_ring(PCIDevice *pci_dev, PvrdmaRing *ring,
rdma_pci_dma_unmap(pci_dev, ring_state, TARGET_PAGE_SIZE);
}
-static int init_dev_ring(PvrdmaRing *ring, struct pvrdma_ring **ring_state,
+static int init_dev_ring(PvrdmaRing *ring, PvrdmaRingState **ring_state,
const char *name, PCIDevice *pci_dev,
dma_addr_t dir_addr, uint32_t num_pages)
{
@@ -114,7 +114,7 @@ static int init_dev_ring(PvrdmaRing *ring, struct pvrdma_ring **ring_state,
/* RX ring is the second */
(*ring_state)++;
rc = pvrdma_ring_init(ring, name, pci_dev,
- (struct pvrdma_ring *)*ring_state,
+ (PvrdmaRingState *)*ring_state,
(num_pages - 1) * TARGET_PAGE_SIZE /
sizeof(struct pvrdma_cqne),
sizeof(struct pvrdma_cqne),
diff --git a/hw/virtio/virtio-net-pci.c b/hw/virtio/virtio-net-pci.c
index 292d13d278..aa0b3caecb 100644
--- a/hw/virtio/virtio-net-pci.c
+++ b/hw/virtio/virtio-net-pci.c
@@ -41,7 +41,8 @@ struct VirtIONetPCI {
static Property virtio_net_properties[] = {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
- DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+ DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
+ DEV_NVECTORS_UNSPECIFIED),
DEFINE_PROP_END_OF_LIST(),
};
@@ -50,6 +51,13 @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
DeviceState *qdev = DEVICE(vpci_dev);
VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ VirtIONet *net = VIRTIO_NET(vdev);
+
+ if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
+ vpci_dev->nvectors = 2 * MAX(net->nic_conf.peers.queues, 1)
+ + 1 /* Config interrupt */
+ + 1 /* Control vq */;
+ }
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));