#define PCI_DEVICE_ID_VMWARE_VMXNET3_REVISION 0x1
#define VMXNET3_MSIX_BAR_SIZE 0x2000
+#define MIN_BUF_SIZE 60
#define VMXNET3_BAR0_IDX (0)
#define VMXNET3_BAR1_IDX (1)
#define VMXNET3_DEVICE_VERSION 0x1
#define VMXNET3_DEVICE_REVISION 0x1
+/* Number of interrupt vectors for non-MSIx modes */
+#define VMXNET3_MAX_NMSIX_INTRS (1)
+
/* Macros for rings descriptors access */
#define VMXNET3_READ_TX_QUEUE_DESCR8(dpa, field) \
(vmw_shmem_ld8(dpa + offsetof(struct Vmxnet3_TxQueueDesc, field)))
vmxnet3_dump_rx_descr(&rxd);
- if (0 != ready_rxcd_pa) {
+ if (ready_rxcd_pa != 0) {
cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
}
rxcd.gen = new_rxcd_gen;
rxcd.rqID = RXQ_IDX + rx_ridx * s->rxq_num;
- if (0 == bytes_left) {
+ if (bytes_left == 0) {
vmxnet3_rx_update_descr(s->rx_pkt, &rxcd);
}
num_frags++;
}
- if (0 != ready_rxcd_pa) {
+ if (ready_rxcd_pa != 0) {
rxcd.eop = 1;
- rxcd.err = (0 != bytes_left);
+ rxcd.err = (bytes_left != 0);
cpu_physical_memory_write(ready_rxcd_pa, &rxcd, sizeof(rxcd));
/* Flush RX descriptor changes */
smp_wmb();
}
- if (0 != new_rxcd_pa) {
+ if (new_rxcd_pa != 0) {
vmxnet3_revert_rxc_descr(s, RXQ_IDX);
}
s->mcast_list_len = list_bytes / sizeof(s->mcast_list[0]);
s->mcast_list = g_realloc(s->mcast_list, list_bytes);
- if (NULL == s->mcast_list) {
- if (0 == s->mcast_list_len) {
+ if (!s->mcast_list) {
+ if (s->mcast_list_len == 0) {
VMW_CFPRN("Current multicast list is empty");
} else {
VMW_ERPRN("Failed to allocate multicast list of %d elements",
(pci_get_byte(s->parent_obj.config + PCI_INTERRUPT_PIN) - 1));
}
+static void vmxnet3_validate_interrupt_idx(bool is_msix, int idx)
+{
+ int max_ints = is_msix ? VMXNET3_MAX_INTRS : VMXNET3_MAX_NMSIX_INTRS;
+ if (idx >= max_ints) {
+ hw_error("Bad interrupt index: %d\n", idx);
+ }
+}
+
+static void vmxnet3_validate_interrupts(VMXNET3State *s)
+{
+ int i;
+
+ VMW_CFPRN("Verifying event interrupt index (%d)", s->event_int_idx);
+ vmxnet3_validate_interrupt_idx(s->msix_used, s->event_int_idx);
+
+ for (i = 0; i < s->txq_num; i++) {
+ int idx = s->txq_descr[i].intr_idx;
+ VMW_CFPRN("Verifying TX queue %d interrupt index (%d)", i, idx);
+ vmxnet3_validate_interrupt_idx(s->msix_used, idx);
+ }
+
+ for (i = 0; i < s->rxq_num; i++) {
+ int idx = s->rxq_descr[i].intr_idx;
+ VMW_CFPRN("Verifying RX queue %d interrupt index (%d)", i, idx);
+ vmxnet3_validate_interrupt_idx(s->msix_used, idx);
+ }
+}
+
+static void vmxnet3_validate_queues(VMXNET3State *s)
+{
+ /*
+ * txq_num and rxq_num are total number of queues
+ * configured by guest. These numbers must not
+ * exceed corresponding maximal values.
+ */
+
+ if (s->txq_num > VMXNET3_DEVICE_MAX_TX_QUEUES) {
+ hw_error("Bad TX queues number: %d\n", s->txq_num);
+ }
+
+ if (s->rxq_num > VMXNET3_DEVICE_MAX_RX_QUEUES) {
+ hw_error("Bad RX queues number: %d\n", s->rxq_num);
+ }
+}
+
static void vmxnet3_activate_device(VMXNET3State *s)
{
int i;
VMXNET3_READ_DRV_SHARED8(s->drv_shmem, devRead.misc.numRxQueues);
VMW_CFPRN("Number of TX/RX queues %u/%u", s->txq_num, s->rxq_num);
- assert(s->txq_num <= VMXNET3_DEVICE_MAX_TX_QUEUES);
+ vmxnet3_validate_queues(s);
qdescr_table_pa =
VMXNET3_READ_DRV_SHARED64(s->drv_shmem, devRead.misc.queueDescPA);
sizeof(s->rxq_descr[i].rxq_stats));
}
+ vmxnet3_validate_interrupts(s);
+
/* Make sure everything is in place before device activation */
smp_wmb();
* memory address. We save it to temp variable and set the
* shared address only after we get the high part
*/
- if (0 == val) {
+ if (val == 0) {
s->device_active = false;
}
s->temp_shared_guest_driver_memory = val;
{
VMXNET3State *s = qemu_get_nic_opaque(nc);
size_t bytes_indicated;
+ uint8_t min_buf[MIN_BUF_SIZE];
if (!vmxnet3_can_receive(nc)) {
VMW_PKPRN("Cannot receive now");
return -1;
}
+ /* Pad to minimum Ethernet frame length */
+ if (size < sizeof(min_buf)) {
+ memcpy(min_buf, buf, size);
+ memset(&min_buf[size], 0, sizeof(min_buf) - size);
+ buf = min_buf;
+ size = sizeof(min_buf);
+ }
+
if (s->peer_has_vhdr) {
vmxnet_rx_pkt_set_vhdr(s->rx_pkt, (struct virtio_net_hdr *)buf);
buf += sizeof(struct virtio_net_hdr);
PCIDevice *d = PCI_DEVICE(s);
if (s->msix_used) {
- msix_vector_unuse(d, VMXNET3_MAX_INTRS);
+ vmxnet3_unuse_msix_vectors(s, VMXNET3_MAX_INTRS);
msix_uninit(d, &s->msix_bar, &s->msix_bar);
}
}
-#define VMXNET3_MSI_NUM_VECTORS (1)
#define VMXNET3_MSI_OFFSET (0x50)
#define VMXNET3_USE_64BIT (true)
#define VMXNET3_PER_VECTOR_MASK (false)
PCIDevice *d = PCI_DEVICE(s);
int res;
- res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MSI_NUM_VECTORS,
+ res = msi_init(d, VMXNET3_MSI_OFFSET, VMXNET3_MAX_NMSIX_INTRS,
VMXNET3_USE_64BIT, VMXNET3_PER_VECTOR_MASK);
if (0 > res) {
VMW_WRPRN("Failed to initialize MSI, error %d", res);
vmxnet3_cleanup_msix(s);
vmxnet3_cleanup_msi(s);
-
- memory_region_destroy(&s->bar0);
- memory_region_destroy(&s->bar1);
- memory_region_destroy(&s->msix_bar);
}
static void vmxnet3_qdev_reset(DeviceState *dev)
.name = "vmxnet3/mcast_list",
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.pre_load = vmxnet3_mcast_list_pre_load,
.fields = (VMStateField[]) {
VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, 0,
vmxnet3_put_tx_stats_to_file(f, &r->txq_stats);
}
-const VMStateInfo txq_descr_info = {
+static const VMStateInfo txq_descr_info = {
.name = "txq_descr",
.get = vmxnet3_get_txq_descr,
.put = vmxnet3_put_txq_descr
}
}
+ vmxnet3_validate_queues(s);
+ vmxnet3_validate_interrupts(s);
+
return 0;
}
-const VMStateInfo rxq_descr_info = {
+static const VMStateInfo rxq_descr_info = {
.name = "rxq_descr",
.get = vmxnet3_get_rxq_descr,
.put = vmxnet3_put_rxq_descr
qemu_put_byte(f, r->is_asserted);
}
-const VMStateInfo int_state_info = {
+static const VMStateInfo int_state_info = {
.name = "int_state",
.get = vmxnet3_get_int_state,
.put = vmxnet3_put_int_state
.name = "vmxnet3",
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.pre_save = vmxnet3_pre_save,
.post_load = vmxnet3_post_load,
- .fields = (VMStateField[]) {
+ .fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
VMSTATE_BOOL(rx_packets_compound, VMXNET3State),
VMSTATE_BOOL(rx_vlan_stripping, VMXNET3State),