Skip to content

Commit 5dd5fab

Browse files
danieldegrassecarlescufi
authored andcommitted
drivers: eth_mcux: remove TX thread and allow for multiple TX buffers
remove the TX thread, as this thread can become starved and unable to reclaim TX buffers from the hardware. Instead reclaim buffers in ISR. Change eth_tx function to first take from the tx_buf_sem, so that multiple TX buffer descriptors can be used effectively. Performance change (as tested with iperf on RT1050) TCP RX: 44.6Mbps->48.6Mbps TCP TX: 38.1Mbps->40.7Mbps Signed-off-by: Daniel DeGrasse <[email protected]>
1 parent af62fbc commit 5dd5fab

File tree

1 file changed

+31
-69
lines changed

1 file changed

+31
-69
lines changed

drivers/ethernet/eth_mcux.c

Lines changed: 31 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,15 @@ struct eth_context {
165165
#endif
166166
enet_handle_t enet_handle;
167167
#if defined(CONFIG_PTP_CLOCK_MCUX)
168-
struct net_pkt *ts_tx_pkt;
169168
const struct device *ptp_clock;
170169
enet_ptp_config_t ptp_config;
171170
double clk_ratio;
172171
struct k_mutex ptp_mutex;
172+
struct k_sem ptp_ts_sem;
173173
#endif
174174
struct k_sem tx_buf_sem;
175175
phy_handle_t *phy_handle;
176176
struct k_sem rx_thread_sem;
177-
struct k_sem tx_thread_sem;
178177
enum eth_mcux_phy_state phy_state;
179178
bool enabled;
180179
bool link_up;
@@ -191,9 +190,6 @@ struct eth_context {
191190
K_KERNEL_STACK_MEMBER(rx_thread_stack, ETH_MCUX_RX_THREAD_STACK_SIZE);
192191
struct k_thread rx_thread;
193192

194-
K_KERNEL_STACK_MEMBER(tx_thread_stack, ETH_MCUX_TX_THREAD_STACK_SIZE);
195-
struct k_thread tx_thread;
196-
197193
/* TODO: FIXME. This Ethernet frame sized buffer is used for
198194
* interfacing with MCUX. How it works is that hardware uses
199195
* DMA scatter buffers to receive a frame, and then public
@@ -710,6 +706,9 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt)
710706
bool timestamped_frame;
711707
#endif
712708

709+
/* Wait for a TX buffer descriptor to be available */
710+
k_sem_take(&context->tx_buf_sem, K_FOREVER);
711+
713712
k_mutex_lock(&context->tx_frame_buf_mutex, K_FOREVER);
714713

715714
if (net_pkt_read(pkt, context->tx_frame_buf, total_len)) {
@@ -722,11 +721,16 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt)
722721
timestamped_frame = eth_get_ptp_data(net_pkt_iface(pkt), pkt);
723722
if (timestamped_frame) {
724723
status = ENET_SendFrame(context->base, &context->enet_handle,
725-
context->tx_frame_buf, total_len, RING_ID, true, NULL);
724+
context->tx_frame_buf, total_len, RING_ID, true, pkt);
726725
if (!status) {
727-
context->ts_tx_pkt = net_pkt_ref(pkt);
728-
} else {
729-
context->ts_tx_pkt = NULL;
726+
net_pkt_ref(pkt);
727+
/*
728+
* Network stack will modify the packet upon return,
729+
* so wait for the packet to be timestamped,
730+
* which will occur within the TX ISR, before
731+
* returning
732+
*/
733+
k_sem_take(&context->ptp_ts_sem, K_FOREVER);
730734
}
731735

732736
} else
@@ -745,7 +749,6 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt)
745749
}
746750

747751
k_mutex_unlock(&context->tx_frame_buf_mutex);
748-
k_sem_take(&context->tx_buf_sem, K_FOREVER);
749752

750753
return 0;
751754
}
@@ -892,7 +895,7 @@ static inline void ts_register_tx_event(struct eth_context *context,
892895
{
893896
struct net_pkt *pkt;
894897

895-
pkt = context->ts_tx_pkt;
898+
pkt = frameinfo->context;
896899
if (pkt && atomic_get(&pkt->atomic_ref) > 0) {
897900
if (eth_get_ptp_data(net_pkt_iface(pkt), pkt)) {
898901
if (frameinfo->isTsAvail) {
@@ -904,6 +907,7 @@ static inline void ts_register_tx_event(struct eth_context *context,
904907
frameinfo->timeStamp.second;
905908

906909
net_if_add_tx_timestamp(pkt);
910+
k_sem_give(&context->ptp_ts_sem);
907911
k_mutex_unlock(&context->ptp_mutex);
908912
}
909913
}
@@ -915,7 +919,6 @@ static inline void ts_register_tx_event(struct eth_context *context,
915919
}
916920
}
917921

918-
context->ts_tx_pkt = NULL;
919922
}
920923
#endif /* CONFIG_PTP_CLOCK_MCUX && CONFIG_NET_L2_PTP */
921924

@@ -932,15 +935,12 @@ static void eth_callback(ENET_Type *base, enet_handle_t *handle,
932935
k_sem_give(&context->rx_thread_sem);
933936
break;
934937
case kENET_TxEvent:
935-
if (!k_is_in_isr()) {
936938
#if defined(CONFIG_PTP_CLOCK_MCUX) && defined(CONFIG_NET_L2_PTP)
937-
/* Register event */
938-
ts_register_tx_event(context, frameinfo);
939+
/* Register event */
940+
ts_register_tx_event(context, frameinfo);
939941
#endif /* CONFIG_PTP_CLOCK_MCUX && CONFIG_NET_L2_PTP */
940-
941-
/* Free the TX buffer. */
942-
k_sem_give(&context->tx_buf_sem);
943-
}
942+
/* Free the TX buffer. */
943+
k_sem_give(&context->tx_buf_sem);
944944
break;
945945
case kENET_ErrEvent:
946946
/* Error event: BABR/BABT/EBERR/LC/RL/UN/PLR. */
@@ -975,37 +975,6 @@ static void eth_rx_thread(void *arg1, void *unused1, void *unused2)
975975
}
976976
}
977977

978-
static void eth_tx_thread(void *arg1, void *unused1, void *unused2)
979-
{
980-
struct eth_context *context = (struct eth_context *)arg1;
981-
982-
while (1) {
983-
if (k_sem_take(&context->tx_thread_sem, K_FOREVER) == 0) {
984-
if (context->enet_handle.txReclaimEnable[RING_ID]) {
985-
ENET_ReclaimTxDescriptor(context->base,
986-
&context->enet_handle, RING_ID);
987-
} else {
988-
enet_handle_t *handle = &context->enet_handle;
989-
990-
if (handle->callback != NULL) {
991-
#if FSL_FEATURE_ENET_QUEUE > 1
992-
handle->callback(context->base,
993-
handle, 0, kENET_TxEvent,
994-
NULL, handle->userData);
995-
#else
996-
handle->callback(context->base,
997-
handle, kENET_TxEvent,
998-
NULL, handle->userData);
999-
#endif
1000-
}
1001-
}
1002-
ENET_EnableInterrupts(context->base,
1003-
kENET_TxBufferInterrupt | kENET_TxFrameInterrupt);
1004-
}
1005-
}
1006-
}
1007-
1008-
1009978
#if defined(CONFIG_ETH_MCUX_PHY_RESET)
1010979
static int eth_phy_reset(const struct device *dev)
1011980
{
@@ -1150,14 +1119,14 @@ static int eth_init(const struct device *dev)
11501119

11511120
#if defined(CONFIG_PTP_CLOCK_MCUX)
11521121
k_mutex_init(&context->ptp_mutex);
1122+
k_sem_init(&context->ptp_ts_sem, 0, 1);
11531123
#endif
11541124
k_mutex_init(&context->rx_frame_buf_mutex);
11551125
k_mutex_init(&context->tx_frame_buf_mutex);
11561126

11571127
k_sem_init(&context->rx_thread_sem, 0, CONFIG_ETH_MCUX_RX_BUFFERS);
1158-
k_sem_init(&context->tx_thread_sem, 0, CONFIG_ETH_MCUX_TX_BUFFERS);
11591128
k_sem_init(&context->tx_buf_sem,
1160-
0, CONFIG_ETH_MCUX_TX_BUFFERS);
1129+
CONFIG_ETH_MCUX_TX_BUFFERS, CONFIG_ETH_MCUX_TX_BUFFERS);
11611130
k_work_init(&context->phy_work, eth_mcux_phy_work);
11621131
k_work_init_delayable(&context->delayed_phy_work,
11631132
eth_mcux_delayed_phy_work);
@@ -1169,13 +1138,6 @@ static int eth_init(const struct device *dev)
11691138
K_PRIO_COOP(2),
11701139
0, K_NO_WAIT);
11711140
k_thread_name_set(&context->rx_thread, "mcux_eth_rx");
1172-
k_thread_create(&context->tx_thread, context->tx_thread_stack,
1173-
K_KERNEL_STACK_SIZEOF(context->tx_thread_stack),
1174-
eth_tx_thread, (void *) context, NULL, NULL,
1175-
K_PRIO_COOP(3),
1176-
0, K_NO_WAIT);
1177-
k_thread_name_set(&context->tx_thread, "mcux_eth_tx");
1178-
11791141
if (context->generate_mac) {
11801142
context->generate_mac(context->mac_addr);
11811143
}
@@ -1355,11 +1317,11 @@ static void eth_mcux_common_isr(const struct device *dev)
13551317
}
13561318

13571319
if (EIR & kENET_TxFrameInterrupt) {
1358-
context->tx_irq_num++;
1359-
ENET_ClearInterruptStatus(context->base, kENET_TxFrameInterrupt);
1360-
ENET_DisableInterrupts(context->base, kENET_TxFrameInterrupt);
1361-
/* schedule tx thread back */
1362-
k_sem_give(&context->tx_thread_sem);
1320+
#if FSL_FEATURE_ENET_QUEUE > 1
1321+
ENET_TransmitIRQHandler(context->base, &context->enet_handle, 0);
1322+
#else
1323+
ENET_TransmitIRQHandler(context->base, &context->enet_handle);
1324+
#endif
13631325
}
13641326

13651327
if (EIR | kENET_TxBufferInterrupt) {
@@ -1400,11 +1362,11 @@ static void eth_mcux_rx_isr(const struct device *dev)
14001362
static void eth_mcux_tx_isr(const struct device *dev)
14011363
{
14021364
struct eth_context *context = dev->data;
1403-
1404-
ENET_DisableInterrupts(context->base, kENET_TxBufferInterrupt | kENET_TxFrameInterrupt);
1405-
ENET_ClearInterruptStatus(context->base, kENET_TxBufferInterrupt | kENET_TxFrameInterrupt);
1406-
/* schedule tx thread back */
1407-
k_sem_give(&context->tx_thread_sem);
1365+
#if FSL_FEATURE_ENET_QUEUE > 1
1366+
ENET_TransmitIRQHandler(context->base, &context->enet_handle, 0);
1367+
#else
1368+
ENET_TransmitIRQHandler(context->base, &context->enet_handle);
1369+
#endif
14081370
}
14091371
#endif
14101372

0 commit comments

Comments
 (0)