drivers: ethernet: eth_stm32: avoid race condition in interface init

rx_thread() is started by eth_initialize(), while dev_data->iface is
populated by eth_iface_init() (called by net_init()).

Usually eth_iface_init() has completed by the time rx_thread() hits its
idle timeout and accesses dev_data->iface, but in case of a time-intensive
SYS_INIT item between eth_initialize() and net_init(), this is not
necessarily the case, causing a NULL dereference. This can be forced by
putting a k_sleep(K_SECONDS(5)) at the top of eth_iface_init().

Start rx_thread() in eth_iface_init() instead (which runs after
eth_initialize() due to init priorities) to make sure everything is
initialized properly.

Signed-off-by: Armin Brauns <armin.brauns@embedded-solutions.at>
This commit is contained in:
Armin Brauns 2023-05-11 09:02:25 +00:00 committed by Carles Cufí
parent d2abe2b661
commit c5701ffa62

View file

@ -1216,15 +1216,6 @@ static int eth_initialize(const struct device *dev)
k_sem_init(&dev_data->tx_int_sem, 0, K_SEM_MAX_LIMIT);
#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */
/* Start interruption-poll thread */
k_thread_create(&dev_data->rx_thread, dev_data->rx_thread_stack,
K_KERNEL_STACK_SIZEOF(dev_data->rx_thread_stack),
rx_thread, (void *) dev, NULL, NULL,
K_PRIO_COOP(CONFIG_ETH_STM32_HAL_RX_THREAD_PRIO),
0, K_NO_WAIT);
k_thread_name_set(&dev_data->rx_thread, "stm_eth");
#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2)
/* Adjust MDC clock range depending on HCLK frequency: */
HAL_ETH_SetMDIOClockRange(heth);
@ -1519,6 +1510,15 @@ static void eth_iface_init(struct net_if *iface)
/* Now that the iface is setup, we are safe to enable IRQs. */
__ASSERT_NO_MSG(cfg->config_func != NULL);
cfg->config_func();
/* Start interruption-poll thread */
k_thread_create(&dev_data->rx_thread, dev_data->rx_thread_stack,
K_KERNEL_STACK_SIZEOF(dev_data->rx_thread_stack),
rx_thread, (void *) dev, NULL, NULL,
K_PRIO_COOP(CONFIG_ETH_STM32_HAL_RX_THREAD_PRIO),
0, K_NO_WAIT);
k_thread_name_set(&dev_data->rx_thread, "stm_eth");
}
}