Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2cddd54 authored by Igor Mitsyanko's avatar Igor Mitsyanko Committed by Kalle Valo
Browse files

qtnfmac: do not use mutexes in timer context



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: default avatarIgor Mitsyanko <igor.mitsyanko.os@quantenna.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 39845020
Loading
Loading
Loading
Loading
+4 −11
Original line number Diff line number Diff line
@@ -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;
}
+0 −19
Original line number Diff line number Diff line
@@ -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_ */
+32 −1
Original line number Diff line number Diff line
@@ -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)
+2 −1
Original line number Diff line number Diff line
@@ -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)
{