aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2015-03-13 08:07:51 -0400
committerKalle Valo <kvalo@codeaurora.org>2015-03-16 12:12:15 -0400
commita9adbcb3355c31faf4274932f513f19225b61747 (patch)
tree5af7a74ee04a3c42f5782d611e52b1b91c41c24f /drivers/net/wireless/mwifiex
parenta3fa71c40f1853d0c27e8f5bc01a722a705d9682 (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.c33
-rw-r--r--drivers/net/wireless/mwifiex/main.c2
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
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
718static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) 718static 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;