Skip to content

Commit 9094e02

Browse files
Freey0cfriedt
authored andcommitted
drivers: ethernet: eth_stm32 add tx async mode
Enable TX transmission asynchronous mode to enhance performance Tested on the nucleo_h743zi board using samples/net/zperf west build -b nucleo_h743zi/stm32h743xx samples/net/zperf/ --pristine -- -DCONFIG_NET_CONFIG_MY_IPV4_ADDR=\"192.168.1.199\" upload cmd: ``` //linux iperf -s -l 1K -p 5001 iperf -s -l 1K -p 5002 -u //shell zperf tcp upload 192.168.1.109 5001 10 1K zperf udp upload 192.168.1.109 5002 10 1K 300M ``` download cmd: ``` //shell zperf tcp download 5001 192.168.1.199 zperf ucp download 5002 192.168.1.199 //linux iperf -l 1K -c 192.168.1.199 -p 5001 iperf -l 1K -c 192.168.1.199 -p 5002 -u ``` before: udp upload: 73.5Mbps/s tcp upload: 71.3Mbps/s udp download: 93.9Mbps/s tcp download: 70.5Mbps/s after: udp upload: 92.2Mbps/s tcp upload: 78.1Mbps/s udp download: 93.7Mbps/s tcp download: 75.2Mbps/s Signed-off-by: WenBin Zhang <[email protected]>
1 parent ab093c2 commit 9094e02

File tree

2 files changed

+144
-22
lines changed

2 files changed

+144
-22
lines changed

drivers/ethernet/Kconfig.stm32_hal

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ config ETH_STM32_HW_CHECKSUM
8686
performances.
8787
See reference manual for more information on this feature.
8888

89+
config ETH_STM32_HAL_TX_ASYNC
90+
bool "Use TX async mode"
91+
depends on ETH_STM32_HAL_API_V2
92+
help
93+
Enable TX transmission asynchronous mode to enhance throughput
94+
performances.
95+
8996
menuconfig PTP_CLOCK_STM32_HAL
9097
bool "STM32 HAL PTP clock driver support"
9198
default y

drivers/ethernet/eth_stm32_hal_v2.c

Lines changed: 137 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,120 @@ static inline uint16_t allocate_tx_buffer(void)
116116
}
117117
}
118118

119+
#if defined(CONFIG_ETH_STM32_HAL_TX_ASYNC)
120+
/* allocate a tx context and mark it as used, the first tx buffer is also allocated */
121+
static struct eth_stm32_tx_context *allocate_tx_context_async(struct net_pkt *pkt)
122+
{
123+
int tx_index;
124+
125+
for (uint16_t index = 0; index < ETH_TX_DESC_CNT; index++) {
126+
if (!dma_tx_context[index].used) {
127+
dma_tx_context[index].used = true;
128+
dma_tx_context[index].pkt = pkt;
129+
tx_index = allocate_tx_buffer();
130+
if (tx_index < 0) {
131+
return NULL;
132+
}
133+
dma_tx_context[index].first_tx_buffer_index = tx_index;
134+
return &dma_tx_context[index];
135+
}
136+
}
137+
return NULL;
138+
}
139+
140+
int eth_stm32_tx(const struct device *dev, struct net_pkt *pkt)
141+
{
142+
struct eth_stm32_hal_dev_data *dev_data = dev->data;
143+
ETH_HandleTypeDef *heth = &dev_data->heth;
144+
int res = 0;
145+
size_t total_len;
146+
size_t remaining_read;
147+
struct eth_stm32_tx_context *ctx = NULL;
148+
struct eth_stm32_tx_buffer_header *buf_header = NULL;
149+
HAL_StatusTypeDef hal_ret = HAL_OK;
150+
151+
#if defined(CONFIG_PTP_CLOCK_STM32_HAL)
152+
bool timestamped_frame;
153+
#endif /* CONFIG_PTP_CLOCK_STM32_HAL */
154+
155+
__ASSERT_NO_MSG(pkt != NULL);
156+
__ASSERT_NO_MSG(pkt->frags != NULL);
157+
158+
total_len = net_pkt_get_len(pkt);
159+
if (total_len > (ETH_STM32_TX_BUF_SIZE * ETH_TXBUFNB)) {
160+
LOG_ERR("PKT too big");
161+
return -EIO;
162+
}
163+
164+
k_mutex_lock(&dev_data->tx_mutex, K_FOREVER);
165+
166+
while (ctx == NULL) {
167+
ctx = allocate_tx_context_async(pkt);
168+
if (ctx == NULL) {
169+
k_sem_take(&dev_data->tx_int_sem, K_MSEC(ETH_DMA_TX_TIMEOUT_MS));
170+
hal_ret = HAL_ETH_ReleaseTxPacket(heth);
171+
__ASSERT_NO_MSG(hal_ret == HAL_OK);
172+
}
173+
}
174+
buf_header = &dma_tx_buffer_header[ctx->first_tx_buffer_index];
175+
176+
#if defined(CONFIG_PTP_CLOCK_STM32_HAL)
177+
timestamped_frame = eth_stm32_is_ptp_pkt(net_pkt_iface(pkt), pkt) ||
178+
net_pkt_is_tx_timestamping(pkt);
179+
if (timestamped_frame) {
180+
/* Enable transmit timestamp */
181+
if (HAL_ETH_PTP_InsertTxTimestamp(heth) != HAL_OK) {
182+
res = -EIO;
183+
goto error;
184+
}
185+
}
186+
#endif /* CONFIG_PTP_CLOCK_STM32_HAL */
187+
188+
remaining_read = total_len;
189+
/* fill and allocate buffer until remaining data fits in one buffer */
190+
while (remaining_read > ETH_STM32_TX_BUF_SIZE) {
191+
res = net_pkt_read(pkt, buf_header->tx_buff.buffer, ETH_STM32_TX_BUF_SIZE);
192+
if (res < 0) {
193+
goto error;
194+
}
195+
196+
const uint16_t next_buffer_id = allocate_tx_buffer();
197+
198+
buf_header->tx_buff.len = ETH_STM32_TX_BUF_SIZE;
199+
/* append new buffer to the linked list */
200+
buf_header->tx_buff.next = &dma_tx_buffer_header[next_buffer_id].tx_buff;
201+
/* and adjust tail pointer */
202+
buf_header = &dma_tx_buffer_header[next_buffer_id];
203+
remaining_read -= ETH_STM32_TX_BUF_SIZE;
204+
}
205+
res = net_pkt_read(pkt, buf_header->tx_buff.buffer, remaining_read);
206+
if (res < 0) {
207+
goto error;
208+
}
209+
buf_header->tx_buff.len = remaining_read;
210+
buf_header->tx_buff.next = NULL;
211+
212+
tx_config.Length = total_len;
213+
tx_config.pData = ctx;
214+
tx_config.TxBuffer = &dma_tx_buffer_header[ctx->first_tx_buffer_index].tx_buff;
215+
216+
if (HAL_ETH_Transmit_IT(heth, &tx_config) != HAL_OK) {
217+
LOG_ERR("HAL_ETH_Transmit: failed!");
218+
res = -EIO;
219+
}
220+
221+
error:
222+
if (res < 0 && ctx) {
223+
/* We need to release the tx context and its buffers */
224+
HAL_ETH_TxFreeCallback((uint32_t *)ctx);
225+
}
226+
227+
k_mutex_unlock(&dev_data->tx_mutex);
228+
229+
return res;
230+
}
231+
#else
232+
119233
/* allocate a tx context and mark it as used, the first tx buffer is also allocated */
120234
static inline struct eth_stm32_tx_context *allocate_tx_context(struct net_pkt *pkt)
121235
{
@@ -132,28 +246,6 @@ static inline struct eth_stm32_tx_context *allocate_tx_context(struct net_pkt *p
132246
}
133247
}
134248

135-
void eth_stm32_setup_mac_filter(ETH_HandleTypeDef *heth)
136-
{
137-
ETH_MACFilterConfigTypeDef MACFilterConf;
138-
HAL_StatusTypeDef __maybe_unused hal_ret;
139-
140-
__ASSERT_NO_MSG(heth != NULL);
141-
142-
hal_ret = HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf);
143-
__ASSERT_NO_MSG(hal_ret == HAL_OK);
144-
145-
MACFilterConf.HashMulticast =
146-
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? ENABLE : DISABLE;
147-
MACFilterConf.PassAllMulticast =
148-
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? DISABLE : ENABLE;
149-
MACFilterConf.HachOrPerfectFilter = DISABLE;
150-
151-
hal_ret = HAL_ETH_SetMACFilterConfig(heth, &MACFilterConf);
152-
__ASSERT_NO_MSG(hal_ret == HAL_OK);
153-
154-
k_sleep(K_MSEC(1));
155-
}
156-
157249
int eth_stm32_tx(const struct device *dev, struct net_pkt *pkt)
158250
{
159251
struct eth_stm32_hal_dev_data *dev_data = dev->data;
@@ -294,6 +386,7 @@ int eth_stm32_tx(const struct device *dev, struct net_pkt *pkt)
294386

295387
return res;
296388
}
389+
#endif /* ETH_STM32_HAL_TX_ASYNC */
297390

298391
struct net_pkt *eth_stm32_rx(const struct device *dev)
299392
{
@@ -559,6 +652,28 @@ void eth_stm32_set_mac_config(const struct device *dev, struct phy_link_state *s
559652
}
560653
}
561654

655+
void eth_stm32_setup_mac_filter(ETH_HandleTypeDef *heth)
656+
{
657+
ETH_MACFilterConfigTypeDef MACFilterConf;
658+
HAL_StatusTypeDef __maybe_unused hal_ret;
659+
660+
__ASSERT_NO_MSG(heth != NULL);
661+
662+
hal_ret = HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf);
663+
__ASSERT_NO_MSG(hal_ret == HAL_OK);
664+
665+
MACFilterConf.HashMulticast =
666+
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? ENABLE : DISABLE;
667+
MACFilterConf.PassAllMulticast =
668+
IS_ENABLED(CONFIG_ETH_STM32_MULTICAST_FILTER) ? DISABLE : ENABLE;
669+
MACFilterConf.HachOrPerfectFilter = DISABLE;
670+
671+
hal_ret = HAL_ETH_SetMACFilterConfig(heth, &MACFilterConf);
672+
__ASSERT_NO_MSG(hal_ret == HAL_OK);
673+
674+
k_sleep(K_MSEC(1));
675+
}
676+
562677
int eth_stm32_hal_start(const struct device *dev)
563678
{
564679
struct eth_stm32_hal_dev_data *dev_data = dev->data;

0 commit comments

Comments
 (0)