diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6510790..732eda0 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2400,7 +2400,7 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
 }
 
 static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
-					 bool assoc)
+					 bool assoc, bool put_bss)
 {
 	struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
 
@@ -2415,6 +2415,10 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 		ieee80211_vif_release_channel(sdata);
 	}
 
+	if (put_bss)
+		cfg80211_put_bss(sdata->local->hw.wiphy, assoc_data->bss);
+
+
 	kfree(assoc_data);
 	sdata->u.mgd.assoc_data = NULL;
 }
@@ -2587,6 +2591,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 	return true;
 }
 
+/** Calling code must dispose of bss reference if it is not NULL. */
 static enum rx_mgmt_action __must_check
 ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 			     struct ieee80211_mgmt *mgmt, size_t len,
@@ -2643,17 +2648,20 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 		return RX_MGMT_NONE;
 	}
 
+	/** bss will be passed back to calling code, and that code must
+	 * deal with properly putting the reference.
+	 */
 	*bss = assoc_data->bss;
 
 	if (status_code != WLAN_STATUS_SUCCESS) {
 		sdata_info(sdata, "%pM denied association (code=%d)\n",
 			   mgmt->sa, status_code);
-		ieee80211_destroy_assoc_data(sdata, false);
+		ieee80211_destroy_assoc_data(sdata, false, false);
 	} else {
 		if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
 			/* oops -- internal error -- send timeout for now */
-			ieee80211_destroy_assoc_data(sdata, false);
-			cfg80211_put_bss(sdata->local->hw.wiphy, *bss);
+			ieee80211_destroy_assoc_data(sdata, false, true);
+			*bss = NULL; /* Ensure no stale references */
 			return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
 		}
 		sdata_info(sdata, "associated\n");
@@ -2663,7 +2671,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
 		 * recalc after assoc_data is NULL but before associated
 		 * is set can cause the interface to go idle
 		 */
-		ieee80211_destroy_assoc_data(sdata, true);
+		ieee80211_destroy_assoc_data(sdata, true, false);
 	}
 
 	return RX_MGMT_CFG80211_RX_ASSOC;
@@ -3105,6 +3113,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 		break;
 	case IEEE80211_STYPE_ASSOC_RESP:
 	case IEEE80211_STYPE_REASSOC_RESP:
+		/* One way or another, must eventually put bss reference
+		 * if it is not NULL.
+		 */
 		rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
 		break;
 	case IEEE80211_STYPE_ACTION:
@@ -3136,6 +3147,9 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 		cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);
 		break;
 	case RX_MGMT_CFG80211_ASSOC_TIMEOUT:
+		/* bss reference is already put at this point, see
+		 * 'internal-error' comment in ieee80211_rx_mgmt_assoc_resp
+		 */
 		cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
 		break;
 	case RX_MGMT_CFG80211_TX_DEAUTH:
@@ -3385,7 +3399,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 
 			memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN);
 
-			ieee80211_destroy_assoc_data(sdata, false);
+			ieee80211_destroy_assoc_data(sdata, false, true);
 
 			mutex_unlock(&ifmgd->mtx);
 			cfg80211_send_assoc_timeout(sdata->dev, bssid);
@@ -3935,6 +3949,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 		return -ENOMEM;
 
 	auth_data->bss = req->bss;
+	cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
 
 	if (req->sae_data_len >= 4) {
 		__le16 *pos = (__le16 *) req->sae_data;
@@ -3998,8 +4013,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 		goto err_clear;
 	}
 
-	/* hold our own reference */
-	cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
 	err = 0;
 	goto out_unlock;
 
@@ -4008,6 +4021,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
 	ifmgd->auth_data = NULL;
  err_free:
+	cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
 	kfree(auth_data);
  out_unlock:
 	mutex_unlock(&ifmgd->mtx);
@@ -4129,6 +4143,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	}
 
 	assoc_data->bss = req->bss;
+	cfg80211_ref_bss(sdata->local->hw.wiphy, assoc_data->bss);
 
 	if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) {
 		if (ifmgd->powersave)
@@ -4259,6 +4274,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
  err_clear:
 	memset(ifmgd->bssid, 0, ETH_ALEN);
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+	cfg80211_put_bss(sdata->local->hw.wiphy, assoc_data->bss);
 	ifmgd->assoc_data = NULL;
  err_free:
 	kfree(assoc_data);
@@ -4364,7 +4380,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 
 	mutex_lock(&ifmgd->mtx);
 	if (ifmgd->assoc_data)
-		ieee80211_destroy_assoc_data(sdata, false);
+		ieee80211_destroy_assoc_data(sdata, false, true);
 	if (ifmgd->auth_data)
 		ieee80211_destroy_auth_data(sdata, false);
 	del_timer_sync(&ifmgd->timer);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 0b6434b..e0fcb4a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -55,6 +55,9 @@ static bool is_uapsd_supported(struct ieee802_11_elems *elems)
 	return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
 }
 
+/** Must (eventually) put the returned value to keep from leaking
+ * a reference to the bss.
+ */
 struct ieee80211_bss *
 ieee80211_bss_info_update(struct ieee80211_local *local,
 			  struct ieee80211_rx_status *rx_status,
@@ -73,6 +76,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 	else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
 		signal = (rx_status->signal * 100) / local->hw.max_signal;
 
+	/* We now own a reference to cbss, have to make sure we
+	 * put it later.
+	 */
 	cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
 					 mgmt, len, signal, GFP_ATOMIC);
 	if (!cbss)
