[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [PATCH v5 10/11] hw/net: GMAC Tx Implementation
From: |
address@hidden |
Subject: |
RE: [PATCH v5 10/11] hw/net: GMAC Tx Implementation |
Date: |
Fri, 17 Nov 2023 09:50:35 +0000 |
-----Original Message-----
From: Nabih Estefan <nabihestefan@google.com>
Sent: Saturday, October 28, 2023 1:56 AM
To: peter.maydell@linaro.org
Cc: qemu-arm@nongnu.org; qemu-devel@nongnu.org; CS20 KFTing
<KFTING@nuvoton.com>; wuhaotsh@google.com; jasonwang@redhat.com; IS20 Avi
Fishman <Avi.Fishman@nuvoton.com>; nabihestefan@google.com; CS20 KWLiu
<KWLIU@nuvoton.com>; IS20 Tomer Maimon <tomer.maimon@nuvoton.com>; IN20 Hila
Miranda-Kuzi <Hila.Miranda-Kuzi@nuvoton.com>
Subject: [PATCH v5 10/11] hw/net: GMAC Tx Implementation
From: Nabih Estefan Diaz <nabihestefan@google.com>
- Implementation of Transmit function for packets
- Implementation for reading and writing from and to descriptors in
memory for Tx
NOTE: This function implements the steps detailed in the datasheet for
transmitting messages from the GMAC.
Change-Id: I5f6148eaf8548726a48db9d4a6d8796bb7ed12dc
Signed-off-by: Nabih Estefan <nabihestefan@google.com>
---
hw/net/npcm_gmac.c | 151 ++++++++++++++++++++++++++++++++++++++++++++
hw/net/trace-events | 1 -
2 files changed, 151 insertions(+), 1 deletion(-)
diff --git a/hw/net/npcm_gmac.c b/hw/net/npcm_gmac.c index
cd59ca5fd4..0098b00a49 100644
--- a/hw/net/npcm_gmac.c
+++ b/hw/net/npcm_gmac.c
@@ -267,6 +267,7 @@ static int gmac_write_tx_desc(dma_addr_t addr, struct
NPCMGMACTxDesc *desc)
}
return 0;
}
+
static int gmac_rx_transfer_frame_to_buffer(uint32_t rx_buf_len,
uint32_t *left_frame,
uint32_t rx_buf_addr, @@ -488,6
+489,156 @@ static ssize_t gmac_receive(NetClientState *nc, const uint8_t *buf,
size_t len)
gmac->regs[R_NPCM_DMA_HOST_RX_DESC] = desc_addr;
return len;
}
+
+static int gmac_tx_get_csum(uint32_t tdes1) {
+ uint32_t mask = TX_DESC_TDES1_CHKSM_INS_CTRL_MASK(tdes1);
+ int csum = 0;
+
+ if (likely(mask > 0)) {
+ csum |= CSUM_IP;
+ }
+ if (likely(mask > 1)) {
+ csum |= CSUM_TCP | CSUM_UDP;
+ }
+
+ return csum;
+}
+
+static void gmac_try_send_next_packet(NPCMGMACState *gmac) {
+ /*
+ * Comments about steps refer to steps for
+ * transmitting in page 384 of datasheet
+ */
+ uint16_t tx_buffer_size = 2048;
+ g_autofree uint8_t *tx_send_buffer = g_malloc(tx_buffer_size);
+ uint32_t desc_addr;
+ struct NPCMGMACTxDesc tx_desc;
+ uint32_t tx_buf_addr, tx_buf_len;
+ uint16_t length = 0;
+ uint8_t *buf = tx_send_buffer;
+ uint32_t prev_buf_size = 0;
+ int csum = 0;
+
+ /* steps 1&2 */
+ if (!gmac->regs[R_NPCM_DMA_HOST_TX_DESC]) {
+ gmac->regs[R_NPCM_DMA_HOST_TX_DESC] =
+ NPCM_DMA_HOST_TX_DESC_MASK(gmac->regs[R_NPCM_DMA_TX_BASE_ADDR]);
+ }
+ desc_addr = gmac->regs[R_NPCM_DMA_HOST_TX_DESC];
+
+ while (true) {
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_RUNNING_FETCHING_STATE);
+ if (gmac_read_tx_desc(desc_addr, &tx_desc)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "TX Descriptor @ 0x%x can't be read\n",
+ desc_addr);
+ return;
+ }
+ /* step 3 */
+
+ trace_npcm_gmac_packet_desc_read(DEVICE(gmac)->canonical_path,
+ desc_addr);
+ trace_npcm_gmac_debug_desc_data(DEVICE(gmac)->canonical_path, &tx_desc,
+ tx_desc.tdes0, tx_desc.tdes1, tx_desc.tdes2,
+ tx_desc.tdes3);
+
+ /* 1 = DMA Owned, 0 = Software Owned */
+ if (!(tx_desc.tdes0 & TX_DESC_TDES0_OWN)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "TX Descriptor @ 0x%x is owned by software\n",
+ desc_addr);
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TU;
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_SUSPENDED_STATE);
+ gmac_update_irq(gmac);
+ return;
+ }
+
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_RUNNING_READ_STATE);
+ /* Give the descriptor back regardless of what happens. */
+ tx_desc.tdes0 &= ~TX_DESC_TDES0_OWN;
+
+ if (tx_desc.tdes1 & TX_DESC_TDES1_FIRST_SEG_MASK) {
+ csum = gmac_tx_get_csum(tx_desc.tdes1);
+ }
+
+ /* step 4 */
+ tx_buf_addr = tx_desc.tdes2;
+ gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
+ tx_buf_len = TX_DESC_TDES1_BFFR1_SZ_MASK(tx_desc.tdes1);
+ buf = &tx_send_buffer[prev_buf_size];
+
+ if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
+ tx_buffer_size = prev_buf_size + tx_buf_len;
+ tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
+ buf = &tx_send_buffer[prev_buf_size];
+ }
+
+ /* step 5 */
+ if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
+ tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @
0x%x\n",
+ __func__, tx_buf_addr);
+ return;
+ }
+ length += tx_buf_len;
+ prev_buf_size += tx_buf_len;
+
+ /* If not chained we'll have a second buffer. */
+ if (!(tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK)) {
+ tx_buf_addr = tx_desc.tdes3;
+ gmac->regs[R_NPCM_DMA_CUR_TX_BUF_ADDR] = tx_buf_addr;
+ tx_buf_len = TX_DESC_TDES1_BFFR2_SZ_MASK(tx_desc.tdes1);
+ buf = &tx_send_buffer[prev_buf_size];
+
+ if ((prev_buf_size + tx_buf_len) > sizeof(buf)) {
+ tx_buffer_size = prev_buf_size + tx_buf_len;
+ tx_send_buffer = g_realloc(tx_send_buffer, tx_buffer_size);
+ buf = &tx_send_buffer[prev_buf_size];
+ }
+
+ if (dma_memory_read(&address_space_memory, tx_buf_addr, buf,
+ tx_buf_len, MEMTXATTRS_UNSPECIFIED)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Failed to read packet @ 0x%x\n",
+ __func__, tx_buf_addr);
+ return;
+ }
+ length += tx_buf_len;
+ prev_buf_size += tx_buf_len;
+ }
+ if (tx_desc.tdes1 & TX_DESC_TDES1_LAST_SEG_MASK) {
+ net_checksum_calculate(tx_send_buffer, length, csum);
+ qemu_send_packet(qemu_get_queue(gmac->nic), tx_send_buffer,
length);
+ trace_npcm_gmac_packet_sent(DEVICE(gmac)->canonical_path, length);
+ buf = tx_send_buffer;
+ length = 0;
+ }
+
+ /* step 6 */
+ gmac_dma_set_state(gmac, NPCM_DMA_STATUS_TX_PROCESS_STATE_SHIFT,
+ NPCM_DMA_STATUS_TX_RUNNING_CLOSING_STATE);
+ gmac_write_tx_desc(desc_addr, &tx_desc);
+ if (tx_desc.tdes1 & TX_DESC_TDES1_TX_END_RING_MASK) {
+ desc_addr = gmac->regs[R_NPCM_DMA_TX_BASE_ADDR];
+ } else if (tx_desc.tdes1 & TX_DESC_TDES1_SEC_ADDR_CHND_MASK) {
+ desc_addr = tx_desc.tdes3;
+ } else {
+ desc_addr += sizeof(tx_desc);
+ }
+ gmac->regs[R_NPCM_DMA_HOST_TX_DESC] = desc_addr;
+
+ /* step 7 */
+ if (tx_desc.tdes1 & TX_DESC_TDES1_INTERR_COMP_MASK) {
+ gmac->regs[R_NPCM_DMA_STATUS] |= NPCM_DMA_STATUS_TI;
+ gmac_update_irq(gmac);
+ }
+ }
+}
+
static void gmac_cleanup(NetClientState *nc) {
/* Nothing to do yet. */
diff --git a/hw/net/trace-events b/hw/net/trace-events index
2843f1eaf8..b19b9ec2ad 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -477,7 +477,6 @@ npcm_gmac_packet_desc_read(const char* name, uint32_t
desc_addr) "%s: attempting npcm_gmac_packet_receive(const char* name, uint32_t
len) "%s: RX packet length: 0x%04" PRIX32
npcm_gmac_packet_receiving_buffer(const char* name, uint32_t buf_len, uint32_t
rx_buf_addr) "%s: Receiving into Buffer size: 0x%04" PRIX32 " at address 0x%04"
PRIX32 npcm_gmac_packet_received(const char* name, uint32_t len) "%s:
Reception finished, packet left: 0x%04" PRIX32 -npcm_gmac_packet_transmit(const
char* name, uint16_t len) "%s: TX transmission start, packed length 0x%04"
PRIX16 npcm_gmac_packet_sent(const char* name, uint16_t len) "%s: TX packet
sent!, length: 0x%04" PRIX16 npcm_gmac_debug_desc_data(const char* name, void*
addr, uint32_t des0, uint32_t des1, uint32_t des2, uint32_t des3)"%s: Address:
%p Descriptor 0: 0x%04" PRIX32 " Descriptor 1: 0x%04" PRIX32 "Descriptor 2:
0x%04" PRIX32 " Descriptor 3: 0x%04" PRIX32
npcm_gmac_packet_tx_desc_data(const char* name, uint32_t tdes0, uint32_t tdes1)
"%s: Tdes0: 0x%04" PRIX32 " Tdes1: 0x%04" PRIX32
--
2.42.0.820.g83a721a137-goog
Reviewed-by: Tyrone Ting <kfting@nuvoton.com>
________________________________
________________________________
The privileged confidential information contained in this email is intended
for use only by the addressees as indicated by the original sender of this
email. If you are not the addressee indicated in this email or are not
responsible for delivery of the email to such a person, please kindly reply to
the sender indicating this fact and delete all copies of it from your computer
and network server immediately. Your cooperation is highly appreciated. It is
advised that any unauthorized use of confidential information of Nuvoton is
strictly prohibited; and any information in this email irrelevant to the
official business of Nuvoton shall be deemed as neither given nor endorsed by
Nuvoton.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- RE: [PATCH v5 10/11] hw/net: GMAC Tx Implementation,
address@hidden <=