diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 164ecf0..5a65144 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1725,6 +1725,10 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata,
 	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
 	mutex_unlock(&ifmgd->mtx);
 
+	/* Have to do this outside the ifmgd->mtx lock. */
+	cancel_work_sync(&ifmgd->monitor_work);
+	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+
 	/*
 	 * must be outside lock due to cfg80211,
 	 * but that's not a problem.
@@ -2579,6 +2583,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 	struct cfg80211_bss *bss = NULL;
 	enum rx_mgmt_action rma = RX_MGMT_NONE;
 	u16 fc;
+	bool cancel_work = false;
 
 	rx_status = (struct ieee80211_rx_status *) skb->cb;
 	mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -2598,9 +2603,11 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 		break;
 	case IEEE80211_STYPE_DEAUTH:
 		rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+		cancel_work = true;
 		break;
 	case IEEE80211_STYPE_DISASSOC:
 		rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+		cancel_work = true;
 		break;
 	case IEEE80211_STYPE_ASSOC_RESP:
 	case IEEE80211_STYPE_REASSOC_RESP:
@@ -2618,6 +2625,12 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 	}
 	mutex_unlock(&ifmgd->mtx);
 
+	if (cancel_work) {
+		/* Have to do this outside the ifmgd->mtx lock. */
+		cancel_work_sync(&ifmgd->monitor_work);
+		cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+	}
+
 	switch (rma) {
 	case RX_MGMT_NONE:
 		/* no action */
@@ -2668,6 +2681,10 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
 			       false, frame_buf);
 	mutex_unlock(&ifmgd->mtx);
 
+	/* Have to do this outside the ifmgd->mtx lock. */
+	cancel_work_sync(&ifmgd->monitor_work);
+	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+
 	/*
 	 * must be outside lock due to cfg80211,
 	 * but that's not a problem.
@@ -2946,6 +2963,13 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+	/* Stop timers before deleting work items, as timers could
+	 * race and re-add the work-items.
+	 * These will be re-established on connection.
+	 */
+	del_timer_sync(&ifmgd->conn_mon_timer);
+	del_timer_sync(&ifmgd->bcn_mon_timer);
+
 	/*
 	 * we need to use atomic bitops for the running bits
 	 * only because both timers might fire at the same
@@ -2954,19 +2978,15 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
 
 	cancel_work_sync(&ifmgd->request_smps_work);
 
+	sdata_err(sdata, "Cancel-work-sync monitor_work, sta_quiesce.\n");
 	cancel_work_sync(&ifmgd->monitor_work);
 	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
 	cancel_work_sync(&ifmgd->csa_connection_drop_work);
 	if (del_timer_sync(&ifmgd->timer))
 		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
 
-	cancel_work_sync(&ifmgd->chswitch_work);
 	if (del_timer_sync(&ifmgd->chswitch_timer))
 		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
-
-	/* these will just be re-established on connection */
-	del_timer_sync(&ifmgd->conn_mon_timer);
-	del_timer_sync(&ifmgd->bcn_mon_timer);
 }
 
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
@@ -3262,6 +3282,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_mgd_auth_data *auth_data;
 	u16 auth_alg;
 	int err;
+	bool maybe_cancel_work = false;
+	bool hit_err_clear = false;
 
 	/* prepare auth data structure */
 
@@ -3319,8 +3341,10 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	/* prep auth_data so we don't go into idle on disassoc */
 	ifmgd->auth_data = auth_data;
 
-	if (ifmgd->associated)
+	if (ifmgd->associated) {
+		maybe_cancel_work = true;
 		ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+	}
 
 	sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
 
@@ -3340,6 +3364,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	goto out_unlock;
 
  err_clear:
+	hit_err_clear = true;
 	memset(ifmgd->bssid, 0, ETH_ALEN);
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
 	ifmgd->auth_data = NULL;
@@ -3348,6 +3373,12 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
  out_unlock:
 	mutex_unlock(&ifmgd->mtx);
 
+	if (maybe_cancel_work && hit_err_clear) {
+		/* Have to do this outside the ifmgd->mtx lock. */
+		cancel_work_sync(&ifmgd->monitor_work);
+		cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+	}
+
 	return err;
 }
 
@@ -3361,6 +3392,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_supported_band *sband;
 	const u8 *ssidie, *ht_ie;
 	int i, err;
+	bool maybe_cancel_work = false;
+	bool hit_err_state = false;
 
 	ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
 	if (!ssidie)
@@ -3372,8 +3405,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 
 	mutex_lock(&ifmgd->mtx);
 
-	if (ifmgd->associated)
+	if (ifmgd->associated) {
+		maybe_cancel_work = true;
 		ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+	}
 
 	if (ifmgd->auth_data && !ifmgd->auth_data->done) {
 		err = -EBUSY;
@@ -3555,9 +3590,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	ifmgd->assoc_data = NULL;
  err_free:
 	kfree(assoc_data);
+	hit_err_state = true;
  out:
 	mutex_unlock(&ifmgd->mtx);
 
+	if (maybe_cancel_work && hit_err_state) {
+		/* Have to do this outside the ifmgd->mtx lock. */
+		cancel_work_sync(&ifmgd->monitor_work);
+		cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+	}
+
 	return err;
 }
 
@@ -3567,6 +3609,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
 	bool tx = !req->local_state_change;
+	bool cancel_work = false;
 
 	mutex_lock(&ifmgd->mtx);
 
@@ -3584,6 +3627,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 	    ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
 		ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
 				       req->reason_code, tx, frame_buf);
+		cancel_work = true;
 	} else {
 		drv_mgd_prepare_tx(sdata->local, sdata);
 		ieee80211_send_deauth_disassoc(sdata, req->bssid,
@@ -3594,6 +3638,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 
 	mutex_unlock(&ifmgd->mtx);
 
+	if (cancel_work) {
+		/* Have to do this outside the ifmgd->mtx lock. */
+		cancel_work_sync(&ifmgd->monitor_work);
+		cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+	}
+
 	__cfg80211_send_deauth(sdata->dev, frame_buf,
 			       IEEE80211_DEAUTH_FRAME_LEN);
 
@@ -3634,6 +3684,10 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
 			       frame_buf);
 	mutex_unlock(&ifmgd->mtx);
 
+	/* Have to do this outside the ifmgd->mtx lock. */
+	cancel_work_sync(&ifmgd->monitor_work);
+	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+
 	__cfg80211_send_disassoc(sdata->dev, frame_buf,
 				 IEEE80211_DEAUTH_FRAME_LEN);
 
