qtnfmac: do not use mutexes in timer context
authorIgor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Mon, 22 Jan 2018 12:46:32 +0000 (15:46 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 24 Jan 2018 16:00:54 +0000 (18:00 +0200)
The function qtnf_scan_done makes use of mutexes which is wrong
since it may be called from timer context. Move scan timeout
handler from timer to deferred work.

Signed-off-by: Igor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
drivers/net/wireless/quantenna/qtnfmac/core.c
drivers/net/wireless/quantenna/qtnfmac/core.h

index edebf23..0398bec 100644 (file)
@@ -595,19 +595,13 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
        return ret;
 }
 
-static void qtnf_scan_timeout(struct timer_list *t)
-{
-       struct qtnf_wmac *mac = from_timer(mac, t, scan_timeout);
-
-       pr_warn("mac%d scan timed out\n", mac->macid);
-       qtnf_scan_done(mac, true);
-}
-
 static int
 qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
        struct qtnf_wmac *mac = wiphy_priv(wiphy);
 
+       cancel_delayed_work_sync(&mac->scan_timeout);
+
        mac->scan_req = request;
 
        if (qtnf_cmd_send_scan(mac)) {
@@ -616,9 +610,8 @@ qtnf_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
                return -EFAULT;
        }
 
-       mac->scan_timeout.function = qtnf_scan_timeout;
-       mod_timer(&mac->scan_timeout,
-                 jiffies + QTNF_SCAN_TIMEOUT_SEC * HZ);
+       queue_delayed_work(mac->bus->workqueue, &mac->scan_timeout,
+                          QTNF_SCAN_TIMEOUT_SEC * HZ);
 
        return 0;
 }
index 66db266..b734251 100644 (file)
@@ -28,23 +28,4 @@ void qtnf_band_init_rates(struct ieee80211_supported_band *band);
 void qtnf_band_setup_htvht_caps(struct qtnf_mac_info *macinfo,
                                struct ieee80211_supported_band *band);
 
-static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
-{
-       struct cfg80211_scan_info info = {
-               .aborted = aborted,
-       };
-
-       if (timer_pending(&mac->scan_timeout))
-               del_timer_sync(&mac->scan_timeout);
-
-       mutex_lock(&mac->mac_lock);
-
-       if (mac->scan_req) {
-               cfg80211_scan_done(mac->scan_req, &info);
-               mac->scan_req = NULL;
-       }
-
-       mutex_unlock(&mac->mac_lock);
-}
-
 #endif /* _QTN_FMAC_CFG80211_H_ */
index b1344d0..cf26c15 100644 (file)
@@ -311,6 +311,37 @@ static void qtnf_mac_init_primary_intf(struct qtnf_wmac *mac)
        vif->cons_tx_timeout_cnt = 0;
 }
 
+static void qtnf_mac_scan_finish(struct qtnf_wmac *mac, bool aborted)
+{
+       struct cfg80211_scan_info info = {
+               .aborted = aborted,
+       };
+
+       mutex_lock(&mac->mac_lock);
+
+       if (mac->scan_req) {
+               cfg80211_scan_done(mac->scan_req, &info);
+               mac->scan_req = NULL;
+       }
+
+       mutex_unlock(&mac->mac_lock);
+}
+
+void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
+{
+       cancel_delayed_work_sync(&mac->scan_timeout);
+       qtnf_mac_scan_finish(mac, aborted);
+}
+
+static void qtnf_mac_scan_timeout(struct work_struct *work)
+{
+       struct qtnf_wmac *mac =
+               container_of(work, struct qtnf_wmac, scan_timeout.work);
+
+       pr_warn("MAC%d: scan timed out\n", mac->macid);
+       qtnf_mac_scan_finish(mac, true);
+}
+
 static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
                                             unsigned int macid)
 {
@@ -334,7 +365,7 @@ static struct qtnf_wmac *qtnf_core_mac_alloc(struct qtnf_bus *bus,
                mac->iflist[i].vifid = i;
                qtnf_sta_list_init(&mac->iflist[i].sta_list);
                mutex_init(&mac->mac_lock);
-               timer_setup(&mac->scan_timeout, NULL, 0);
+               INIT_DELAYED_WORK(&mac->scan_timeout, qtnf_mac_scan_timeout);
                mac->iflist[i].stats64 =
                        netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
                if (!mac->iflist[i].stats64)
index 29f38bd..3b884c8 100644 (file)
@@ -133,7 +133,7 @@ struct qtnf_wmac {
        struct qtnf_vif iflist[QTNF_MAX_INTF];
        struct cfg80211_scan_request *scan_req;
        struct mutex mac_lock;  /* lock during wmac speicific ops */
-       struct timer_list scan_timeout;
+       struct delayed_work scan_timeout;
 };
 
 struct qtnf_hw_info {
@@ -168,6 +168,7 @@ void qtnf_update_tx_stats(struct net_device *ndev, const struct sk_buff *skb);
 void qtnf_virtual_intf_cleanup(struct net_device *ndev);
 
 void qtnf_netdev_updown(struct net_device *ndev, bool up);
+void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted);
 
 static inline struct qtnf_vif *qtnf_netdev_get_priv(struct net_device *dev)
 {