wilc1000 driver supports WILC3000, a combo wifi/bluetooth chip. This chip needs a firmware for each radio. Before bringing support for the bluetooth side (and so, before adding bluetooth firmware load and start), add a dedicated lock around firmware loading and startup for wlan side. The bluetooth part will also use this lock to ensure that both firmware are not being loaded/started at the same time. Signed-off-by: Alexis Lothoré <alexis.lothore@xxxxxxxxxxx> --- drivers/net/wireless/microchip/wilc1000/cfg80211.c | 2 ++ drivers/net/wireless/microchip/wilc1000/netdev.c | 5 +++++ drivers/net/wireless/microchip/wilc1000/netdev.h | 2 ++ 3 files changed, 9 insertions(+) diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c index e7aa0f9919232350761d51cbb1b5be87ca39e855..393fff618f919c5a6d3f4a7d894b187399455fb8 100644 --- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c +++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c @@ -1736,6 +1736,7 @@ static void wlan_init_locks(struct wilc *wl) mutex_init(&wl->cfg_cmd_lock); mutex_init(&wl->vif_mutex); mutex_init(&wl->deinit_lock); + mutex_init(&wl->radio_fw_start); spin_lock_init(&wl->txq_spinlock); mutex_init(&wl->txq_add_to_head_cs); @@ -1755,6 +1756,7 @@ void wlan_deinit_locks(struct wilc *wilc) mutex_destroy(&wilc->txq_add_to_head_cs); mutex_destroy(&wilc->vif_mutex); mutex_destroy(&wilc->deinit_lock); + mutex_destroy(&wilc->radio_fw_start); cleanup_srcu_struct(&wilc->srcu); } diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c index af298021e05041ba4b16a94c8ee768407a208dfc..d24859d12ccd535c966a9b7f46378ac3b3a21d7b 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.c +++ b/drivers/net/wireless/microchip/wilc1000/netdev.c @@ -4,6 +4,7 @@ * All rights reserved. */ +#include "linux/mutex.h" #include <linux/irq.h> #include <linux/kthread.h> #include <linux/firmware.h> @@ -534,6 +535,8 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) goto fail_irq_init; } + mutex_lock(&wl->radio_fw_start); + ret = wilc_wlan_get_firmware(dev); if (ret) goto fail_irq_enable; @@ -562,6 +565,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) netdev_err(dev, "Failed to configure firmware\n"); goto fail_fw_start; } + mutex_unlock(&wl->radio_fw_start); wl->initialized = true; return 0; @@ -569,6 +573,7 @@ static int wilc_wlan_initialize(struct net_device *dev, struct wilc_vif *vif) wilc_wlan_stop(wl, vif); fail_irq_enable: + mutex_unlock(&wl->radio_fw_start); if (!wl->dev_irq_num && wl->hif_func->disable_interrupt) wl->hif_func->disable_interrupt(wl); diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.h b/drivers/net/wireless/microchip/wilc1000/netdev.h index 95bc8b8fe65a584615b6b9021d08d11e4b36408b..5837f8ffe548dad1b756cdbd8543636f2be0e9b0 100644 --- a/drivers/net/wireless/microchip/wilc1000/netdev.h +++ b/drivers/net/wireless/microchip/wilc1000/netdev.h @@ -287,6 +287,8 @@ struct wilc { struct ieee80211_supported_band band; u32 cipher_suites[ARRAY_SIZE(wilc_cipher_suites)]; u8 nv_mac_address[ETH_ALEN]; + /* Lock to prevent concurrent start of wlan/bluetooth firmware */ + struct mutex radio_fw_start; }; struct wilc_wfi_mon_priv { -- 2.48.0