diff options
Diffstat (limited to 'hw/net')
-rw-r--r-- | hw/net/allwinner_emac.c | 6 | ||||
-rw-r--r-- | hw/net/cadence_gem.c | 4 | ||||
-rw-r--r-- | hw/net/fsl_etsec/rings.c | 8 | ||||
-rw-r--r-- | hw/net/pcnet.c | 1 | ||||
-rw-r--r-- | hw/net/spapr_llan.c | 3 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 50 | ||||
-rw-r--r-- | hw/net/vmxnet3.c | 58 | ||||
-rw-r--r-- | hw/net/xilinx_axienet.c | 25 |
8 files changed, 124 insertions, 31 deletions
diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c index 469f2f0ede..d780ba0fcb 100644 --- a/hw/net/allwinner_emac.c +++ b/hw/net/allwinner_emac.c @@ -27,11 +27,11 @@ static uint8_t padding[60]; static void mii_set_link(RTL8201CPState *mii, bool link_ok) { if (link_ok) { - mii->bmsr |= MII_BMSR_LINK_ST; + mii->bmsr |= MII_BMSR_LINK_ST | MII_BMSR_AN_COMP; mii->anlpar |= MII_ANAR_TXFD | MII_ANAR_10FD | MII_ANAR_10 | MII_ANAR_CSMACD; } else { - mii->bmsr &= ~MII_BMSR_LINK_ST; + mii->bmsr &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP); mii->anlpar = MII_ANAR_TX; } } @@ -391,9 +391,11 @@ static void aw_emac_write(void *opaque, hwaddr offset, uint64_t value, break; case EMAC_INT_CTL_REG: s->int_ctl = value; + aw_emac_update_irq(s); break; case EMAC_INT_STA_REG: s->int_sta &= ~value; + aw_emac_update_irq(s); break; case EMAC_MAC_MADR_REG: s->phy_target = value; diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 92dc2f21fa..e34b25e734 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1093,7 +1093,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size) uint32_t phy_addr, reg_num; phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT; - if (phy_addr == BOARD_PHY_ADDRESS) { + if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) { reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT; retval &= 0xFFFF0000; retval |= gem_phy_read(s, reg_num); @@ -1193,7 +1193,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val, uint32_t phy_addr, reg_num; phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT; - if (phy_addr == BOARD_PHY_ADDRESS) { + if (phy_addr == BOARD_PHY_ADDRESS || phy_addr == 0) { reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT; gem_phy_write(s, reg_num, val); } diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c index 77602722b3..e36cfbe76d 100644 --- a/hw/net/fsl_etsec/rings.c +++ b/hw/net/fsl_etsec/rings.c @@ -195,8 +195,8 @@ static void process_tx_fcb(eTSEC *etsec) /* if packet is IP4 and IP checksum is requested */ if (flags & FCB_TX_IP && flags & FCB_TX_CIP) { - /* do IP4 checksum (TODO This funtion does TCP/UDP checksum but not sure - * if it also does IP4 checksum. */ + /* do IP4 checksum (TODO This function does TCP/UDP checksum + * but not sure if it also does IP4 checksum.) */ net_checksum_calculate(etsec->tx_buffer + 8, etsec->tx_buffer_len - 8); } @@ -592,7 +592,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr) /* TODO: Broadcast and Multicast */ - if (bd.flags | BD_INTERRUPT) { + if (bd.flags & BD_INTERRUPT) { /* Set RXFx */ etsec->regs[RSTAT].value |= 1 << (7 - ring_nbr); @@ -601,7 +601,7 @@ void etsec_walk_rx_ring(eTSEC *etsec, int ring_nbr) } } else { - if (bd.flags | BD_INTERRUPT) { + if (bd.flags & BD_INTERRUPT) { /* Set IEVENT */ ievent_set(etsec, IEVENT_RXB); } diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c index 7cb47b3f1f..ebe505784d 100644 --- a/hw/net/pcnet.c +++ b/hw/net/pcnet.c @@ -718,7 +718,6 @@ static void pcnet_s_reset(PCNetState *s) s->csr[94] = 0x0000; s->csr[100] = 0x0200; s->csr[103] = 0x0105; - s->csr[103] = 0x0105; s->csr[112] = 0x0000; s->csr[114] = 0x0000; s->csr[122] = 0x0000; diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c index f6fbcb56bf..c433337b67 100644 --- a/hw/net/spapr_llan.c +++ b/hw/net/spapr_llan.c @@ -29,6 +29,7 @@ #include "hw/qdev.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" +#include "sysemu/sysemu.h" #include <libfdt.h> @@ -213,6 +214,8 @@ static int spapr_vlan_init(VIOsPAPRDevice *sdev) object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev); qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); + add_boot_device_path(dev->nicconf.bootindex, DEVICE(dev), ""); + return 0; } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index fd23c4627e..33bd233a2d 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -222,13 +222,33 @@ static char *mac_strdup_printf(const uint8_t *mac) mac[1], mac[2], mac[3], mac[4], mac[5]); } +static intList *get_vlan_table(VirtIONet *n) +{ + intList *list, *entry; + int i, j; + + list = NULL; + for (i = 0; i < MAX_VLAN >> 5; i++) { + for (j = 0; n->vlans[i] && j <= 0x1f; j++) { + if (n->vlans[i] & (1U << j)) { + entry = g_malloc0(sizeof(*entry)); + entry->value = (i << 5) + j; + entry->next = list; + list = entry; + } + } + } + + return list; +} + static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) { VirtIONet *n = qemu_get_nic_opaque(nc); + VirtIODevice *vdev = VIRTIO_DEVICE(n); RxFilterInfo *info; strList *str_list, *entry; - intList *int_list, *int_entry; - int i, j; + int i; info = g_malloc0(sizeof(*info)); info->name = g_strdup(nc->name); @@ -273,19 +293,15 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc) str_list = entry; } info->multicast_table = str_list; + info->vlan_table = get_vlan_table(n); - int_list = NULL; - for (i = 0; i < MAX_VLAN >> 5; i++) { - for (j = 0; n->vlans[i] && j < 0x1f; j++) { - if (n->vlans[i] & (1U << j)) { - int_entry = g_malloc0(sizeof(*int_entry)); - int_entry->value = (i << 5) + j; - int_entry->next = int_list; - int_list = int_entry; - } - } + if (!((1 << VIRTIO_NET_F_CTRL_VLAN) & vdev->guest_features)) { + info->vlan = RX_STATE_ALL; + } else if (!info->vlan_table) { + info->vlan = RX_STATE_NONE; + } else { + info->vlan = RX_STATE_NORMAL; } - info->vlan_table = int_list; /* enable event notification after query */ nc->rxfilter_notify_enabled = 1; @@ -514,6 +530,12 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) } vhost_net_ack_features(tap_get_vhost_net(nc->peer), features); } + + if ((1 << VIRTIO_NET_F_CTRL_VLAN) & features) { + memset(n->vlans, 0, MAX_VLAN >> 3); + } else { + memset(n->vlans, 0xff, MAX_VLAN >> 3); + } } static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, @@ -655,7 +677,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, goto error; } - if (in_use + mac_data.entries <= MAC_TABLE_ENTRIES) { + if (mac_data.entries <= MAC_TABLE_ENTRIES - in_use) { s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN], mac_data.entries * ETH_ALEN); if (s != mac_data.entries * ETH_ALEN) { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 5be807ce82..ddcee4bd21 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -52,6 +52,9 @@ #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))) @@ -1305,6 +1308,51 @@ static bool vmxnet3_verify_intx(VMXNET3State *s, int intx) (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; @@ -1351,7 +1399,7 @@ static void vmxnet3_activate_device(VMXNET3State *s) 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); @@ -1447,6 +1495,8 @@ static void vmxnet3_activate_device(VMXNET3State *s) sizeof(s->rxq_descr[i].rxq_stats)); } + vmxnet3_validate_interrupts(s); + /* Make sure everything is in place before device activation */ smp_wmb(); @@ -2005,7 +2055,6 @@ vmxnet3_cleanup_msix(VMXNET3State *s) } } -#define VMXNET3_MSI_NUM_VECTORS (1) #define VMXNET3_MSI_OFFSET (0x50) #define VMXNET3_USE_64BIT (true) #define VMXNET3_PER_VECTOR_MASK (false) @@ -2016,7 +2065,7 @@ vmxnet3_init_msi(VMXNET3State *s) 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); @@ -2342,6 +2391,9 @@ static int vmxnet3_post_load(void *opaque, int version_id) } } + vmxnet3_validate_queues(s); + vmxnet3_validate_interrupts(s); + return 0; } diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 0bd5eda199..dbeb3c9a25 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -98,7 +98,7 @@ static unsigned int tdk_read(struct PHY *phy, unsigned int req) r |= 1; break; case 17: - /* Marvel PHY on many xilinx boards. */ + /* Marvell PHY on many xilinx boards. */ r = 0x8000; /* 1000Mb */ break; case 18: @@ -142,6 +142,9 @@ tdk_write(struct PHY *phy, unsigned int req, unsigned int data) phy->regs[regnum] = data; break; } + + /* Unconditionally clear regs[BMCR][BMCR_RESET] */ + phy->regs[0] &= ~0x8000; } static void @@ -945,9 +948,15 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) Error *local_errp = NULL; object_property_add_link(OBJECT(ds), "enet", "xlnx.axi-ethernet", - (Object **) &ds->enet, &local_errp); + (Object **) &ds->enet, + object_property_allow_set_link, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &local_errp); object_property_add_link(OBJECT(cs), "enet", "xlnx.axi-ethernet", - (Object **) &cs->enet, &local_errp); + (Object **) &cs->enet, + object_property_allow_set_link, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &local_errp); if (local_errp) { goto xilinx_enet_realize_fail; } @@ -982,10 +991,16 @@ static void xilinx_enet_init(Object *obj) SysBusDevice *sbd = SYS_BUS_DEVICE(obj); object_property_add_link(obj, "axistream-connected", TYPE_STREAM_SLAVE, - (Object **) &s->tx_data_dev, &error_abort); + (Object **) &s->tx_data_dev, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &error_abort); object_property_add_link(obj, "axistream-control-connected", TYPE_STREAM_SLAVE, - (Object **) &s->tx_control_dev, &error_abort); + (Object **) &s->tx_control_dev, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &error_abort); object_initialize(&s->rx_data_dev, sizeof(s->rx_data_dev), TYPE_XILINX_AXI_ENET_DATA_STREAM); |