mwifiex: lock main process till reinitialization of vif is over
authorAvinash Patil <patila@marvell.com>
Fri, 13 Mar 2015 12:07:51 +0000 (17:37 +0530)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 16 Mar 2015 16:12:15 +0000 (18:12 +0200)
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>
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h

index b0778a699bbc4472096d90a769a4c5d08e292457..fc3bbe77eb18b76bb23231d6a69425bcd880b92b 100644 (file)
@@ -717,6 +717,9 @@ mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
 
 static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
 {
+       struct mwifiex_adapter *adapter = priv->adapter;
+       unsigned long flags;
+
        priv->mgmt_frame_mask = 0;
        if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
                             HostCmd_ACT_GEN_SET, 0,
@@ -727,6 +730,25 @@ static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
        }
 
        mwifiex_deauthenticate(priv, NULL);
+
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       adapter->main_locked = true;
+       if (adapter->mwifiex_processing) {
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+               flush_workqueue(adapter->workqueue);
+       } else {
+               spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+       }
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       adapter->rx_locked = true;
+       if (adapter->rx_processing) {
+               spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+               flush_workqueue(adapter->rx_workqueue);
+       } else {
+       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+       }
+
        mwifiex_free_priv(priv);
        priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
        priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
@@ -740,6 +762,9 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
                             struct net_device *dev,
                             enum nl80211_iftype type)
 {
+       struct mwifiex_adapter *adapter = priv->adapter;
+       unsigned long flags;
+
        mwifiex_init_priv(priv);
 
        priv->bss_mode = type;
@@ -770,6 +795,14 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
                return -EOPNOTSUPP;
        }
 
+       spin_lock_irqsave(&adapter->main_proc_lock, flags);
+       adapter->main_locked = false;
+       spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
+
+       spin_lock_irqsave(&adapter->rx_proc_lock, flags);
+       adapter->rx_locked = false;
+       spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
+
        return 0;
 }
 
index 42bf8846771b184d48375489290e004651d2552e..9c11eb882a0e8463d4436f2e2139ceb05c5eb529 100644 (file)
@@ -189,7 +189,7 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
        spin_lock_irqsave(&adapter->main_proc_lock, flags);
 
        /* Check if already processing */
-       if (adapter->mwifiex_processing) {
+       if (adapter->mwifiex_processing || adapter->main_locked) {
                adapter->more_task_flag = true;
                spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
                goto exit_main_proc;
index a0908c64103a4ae422cdbe4b6480051ff6e631a0..04ef618de23c562971f347d7d5d977f8ec43ae93 100644 (file)
@@ -772,6 +772,7 @@ struct mwifiex_adapter {
        bool rx_processing;
        bool delay_main_work;
        bool rx_locked;
+       bool main_locked;
        struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM];
        /* spin lock for init/shutdown */
        spinlock_t mwifiex_lock;