diff options
author | Avinash Patil <patila@marvell.com> | 2015-03-13 08:07:51 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2015-03-16 12:12:15 -0400 |
commit | a9adbcb3355c31faf4274932f513f19225b61747 (patch) | |
tree | 5af7a74ee04a3c42f5782d611e52b1b91c41c24f /drivers/net/wireless/mwifiex | |
parent | a3fa71c40f1853d0c27e8f5bc01a722a705d9682 (diff) |
mwifiex: lock main process till reinitialization of vif is over
A crash was detected while changing virtual interface type is in
progress. This was tracked to race condition in accessing bss_priority
table while change is in progress. This patch ensures that main_process
and rx_process works are locked while we change virtual interface.
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 1 |
3 files changed, 35 insertions, 1 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index b0778a699bbc..fc3bbe77eb18 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -717,6 +717,9 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) | |||
717 | 717 | ||
718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | 718 | static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) |
719 | { | 719 | { |
720 | struct mwifiex_adapter *adapter = priv->adapter; | ||
721 | unsigned long flags; | ||
722 | |||
720 | priv->mgmt_frame_mask = 0; | 723 | priv->mgmt_frame_mask = 0; |
721 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, | 724 | if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, |
722 | HostCmd_ACT_GEN_SET, 0, | 725 | HostCmd_ACT_GEN_SET, 0, |
@@ -727,6 +730,25 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) | |||
727 | } | 730 | } |
728 | 731 | ||
729 | mwifiex_deauthenticate(priv, NULL); | 732 | mwifiex_deauthenticate(priv, NULL); |
733 | |||
734 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
735 | adapter->main_locked = true; | ||
736 | if (adapter->mwifiex_processing) { | ||
737 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
738 | flush_workqueue(adapter->workqueue); | ||
739 | } else { | ||
740 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
741 | } | ||
742 | |||
743 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
744 | adapter->rx_locked = true; | ||
745 | if (adapter->rx_processing) { | ||
746 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
747 | flush_workqueue(adapter->rx_workqueue); | ||
748 | } else { | ||
749 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
750 | } | ||
751 | |||
730 | mwifiex_free_priv(priv); | 752 | mwifiex_free_priv(priv); |
731 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; | 753 | priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; |
732 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; | 754 | priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; |
@@ -740,6 +762,9 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, | |||
740 | struct net_device *dev, | 762 | struct net_device *dev, |
741 | enum nl80211_iftype type) | 763 | enum nl80211_iftype type) |
742 | { | 764 | { |
765 | struct mwifiex_adapter *adapter = priv->adapter; | ||
766 | unsigned long flags; | ||
767 | |||
743 | mwifiex_init_priv(priv); | 768 | mwifiex_init_priv(priv); |
744 | 769 | ||
745 | priv->bss_mode = type; | 770 | priv->bss_mode = type; |
@@ -770,6 +795,14 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, | |||
770 | return -EOPNOTSUPP; | 795 | return -EOPNOTSUPP; |
771 | } | 796 | } |
772 | 797 | ||
798 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | ||
799 | adapter->main_locked = false; | ||
800 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | ||
801 | |||
802 | spin_lock_irqsave(&adapter->rx_proc_lock, flags); | ||
803 | adapter->rx_locked = false; | ||
804 | spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); | ||
805 | |||
773 | return 0; | 806 | return 0; |
774 | } | 807 | } |
775 | 808 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 42bf8846771b..9c11eb882a0e 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -189,7 +189,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) | |||
189 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | 189 | spin_lock_irqsave(&adapter->main_proc_lock, flags); |
190 | 190 | ||
191 | /* Check if already processing */ | 191 | /* Check if already processing */ |
192 | if (adapter->mwifiex_processing) { | 192 | if (adapter->mwifiex_processing || adapter->main_locked) { |
193 | adapter->more_task_flag = true; | 193 | adapter->more_task_flag = true; |
194 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); | 194 | spin_unlock_irqrestore(&adapter->main_proc_lock, flags); |
195 | goto exit_main_proc; | 195 | goto exit_main_proc; |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index a0908c64103a..04ef618de23c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -772,6 +772,7 @@ struct mwifiex_adapter { | |||
772 | bool rx_processing; | 772 | bool rx_processing; |
773 | bool delay_main_work; | 773 | bool delay_main_work; |
774 | bool rx_locked; | 774 | bool rx_locked; |
775 | bool main_locked; | ||
775 | struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; | 776 | struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; |
776 | /* spin lock for init/shutdown */ | 777 | /* spin lock for init/shutdown */ |
777 | spinlock_t mwifiex_lock; | 778 | spinlock_t mwifiex_lock; |