diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-06-08 16:26:51 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-06-08 16:26:51 +0100 |
commit | 0d2fa03dae4fbe185a082f361342b1e30aed4582 (patch) | |
tree | 2ee9e184f32e4884cf78078841e31df7f15ffea5 /hw/net/ftgmac100.c | |
parent | ed6b018ef7667f73aa25190b04e1fe3a4a87c323 (diff) | |
parent | 113f31c06c6bf16451892b2459d83c9b9c5e9844 (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180608' into staging
target-arm queue:
* arm_gicv3_kvm: fix migration of registers corresponding to
IRQs 992 to 1020 in the KVM GIC
* aspeed: remove ignore_memory_transaction_failures on all boards
* aspeed: add support for the witherspoon-bmc board
* aspeed: add an I2C RTC device and EEPROM I2C devices
* aspeed: add the pc9552 chips to the witherspoon machine
* ftgmac100: fix various bugs
* hw/arm: Remove the deprecated xlnx-ep108 machine
* hw/i2c: Add trace events
* add missing '\n' on various qemu_log() logging strings
* sdcard: clean up spec version support so we report the
right spec version to the guest and only implement the
commands that are supposed to be present in that version
# gpg: Signature made Fri 08 Jun 2018 13:36:37 BST
# gpg: using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20180608: (31 commits)
sdcard: Disable CMD19/CMD23 for Spec v2
sdcard: Reflect when the Spec v3 is supported in the Config Register (SCR)
sdcard: Disable SEND_IF_COND (CMD8) for Spec v1
sdcard: Add a 'spec_version' property, default to Spec v2.00
sdcard: Allow commands valid in SPI mode
sdcard: Update the Configuration Register (SCR) to Spec Version 1.10
target/xtensa: Add trailing '\n' to qemu_log() calls
RISC-V: Add trailing '\n' to qemu_log() calls
target/m68k: Add trailing '\n' to qemu_log() call
target/arm: Add trailing '\n' to qemu_log() calls
stellaris: Add trailing '\n' to qemu_log() calls
hw/mips/boston: Add trailing '\n' to qemu_log() calls
hw/core/register: Add trailing '\n' to qemu_log() call
ppc/pnv: Add trailing '\n' to qemu_log() calls
xilinx-dp: Add trailing '\n' to qemu_log() call
hw/digic: Add trailing '\n' to qemu_log() calls
hw/sd/milkymist-memcard: Add trailing '\n' to qemu_log() call
hw/i2c: Add trace events
hw/arm: Remove the deprecated xlnx-ep108 machine
ftgmac100: remove check on runt messages
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/net/ftgmac100.c')
-rw-r--r-- | hw/net/ftgmac100.c | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c index 3300e8ef4a..909c1182ee 100644 --- a/hw/net/ftgmac100.c +++ b/hw/net/ftgmac100.c @@ -207,16 +207,18 @@ typedef struct { /* * Max frame size for the receiving buffer */ -#define FTGMAC100_MAX_FRAME_SIZE 10240 +#define FTGMAC100_MAX_FRAME_SIZE 9220 /* Limits depending on the type of the frame * * 9216 for Jumbo frames (+ 4 for VLAN) * 1518 for other frames (+ 4 for VLAN) */ -static int ftgmac100_max_frame_size(FTGMAC100State *s) +static int ftgmac100_max_frame_size(FTGMAC100State *s, uint16_t proto) { - return (s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518) + 4; + int max = (s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518); + + return max + (proto == ETH_P_VLAN ? 4 : 0); } static void ftgmac100_update_irq(FTGMAC100State *s) @@ -408,7 +410,6 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, uint8_t *ptr = s->frame; uint32_t addr = tx_descriptor; uint32_t flags = 0; - int max_frame_size = ftgmac100_max_frame_size(s); while (1) { FTGMAC100Desc bd; @@ -427,11 +428,12 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, flags = bd.des1; } - len = bd.des0 & 0x3FFF; - if (frame_size + len > max_frame_size) { + len = FTGMAC100_TXDES0_TXBUF_SIZE(bd.des0); + if (frame_size + len > sizeof(s->frame)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n", __func__, len); - len = max_frame_size - frame_size; + s->isr |= FTGMAC100_INT_XPKT_LOST; + len = sizeof(s->frame) - frame_size; } if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) { @@ -441,6 +443,22 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, break; } + /* Check for VLAN */ + if (bd.des0 & FTGMAC100_TXDES0_FTS && + bd.des1 & FTGMAC100_TXDES1_INS_VLANTAG && + be16_to_cpu(PKT_GET_ETH_HDR(ptr)->h_proto) != ETH_P_VLAN) { + if (frame_size + len + 4 > sizeof(s->frame)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n", + __func__, len); + s->isr |= FTGMAC100_INT_XPKT_LOST; + len = sizeof(s->frame) - frame_size - 4; + } + memmove(ptr + 16, ptr + 12, len - 12); + stw_be_p(ptr + 12, ETH_P_VLAN); + stw_be_p(ptr + 14, bd.des1); + len += 4; + } + ptr += len; frame_size += len; if (bd.des0 & FTGMAC100_TXDES0_LTS) { @@ -758,8 +776,8 @@ static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len) return 0; } - /* TODO: this does not seem to work for ftgmac100 */ - mcast_idx = net_crc32(buf, ETH_ALEN) >> 26; + mcast_idx = net_crc32_le(buf, ETH_ALEN); + mcast_idx = (~(mcast_idx >> 2)) & 0x3f; if (!(s->math[mcast_idx / 32] & (1 << (mcast_idx % 32)))) { return 0; } @@ -788,7 +806,8 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, uint32_t buf_len; size_t size = len; uint32_t first = FTGMAC100_RXDES0_FRS; - int max_frame_size = ftgmac100_max_frame_size(s); + uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(buf)->h_proto); + int max_frame_size = ftgmac100_max_frame_size(s, proto); if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) != (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) { @@ -803,12 +822,6 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, return size; } - if (size < 64 && !(s->maccr & FTGMAC100_MACCR_RX_RUNT)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: dropped runt frame of %zd bytes\n", - __func__, size); - return size; - } - if (!ftgmac100_filter(s, buf, size)) { return size; } @@ -820,9 +833,9 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, /* Huge frames are truncated. */ if (size > max_frame_size) { - size = max_frame_size; qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n", __func__, size); + size = max_frame_size; flags |= FTGMAC100_RXDES0_FTL; } @@ -861,7 +874,20 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, buf_len += size - 4; } buf_addr = bd.des3; - dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + if (first && proto == ETH_P_VLAN && buf_len >= 18) { + bd.des1 = lduw_be_p(buf + 14) | FTGMAC100_RXDES1_VLANTAG_AVAIL; + + if (s->maccr & FTGMAC100_MACCR_RM_VLAN) { + dma_memory_write(&address_space_memory, buf_addr, buf, 12); + dma_memory_write(&address_space_memory, buf_addr + 12, buf + 16, + buf_len - 16); + } else { + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + } + } else { + bd.des1 = 0; + dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); + } buf += buf_len; if (size < 4) { dma_memory_write(&address_space_memory, buf_addr + buf_len, @@ -940,8 +966,6 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) object_get_typename(OBJECT(dev)), DEVICE(dev)->id, s); qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); - - s->frame = g_malloc(FTGMAC100_MAX_FRAME_SIZE); } static const VMStateDescription vmstate_ftgmac100 = { |