diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 513a85403924dcb25ddc8c97d83ea58cbc75af49..406cf1cb945cfe330be0185f17dd7cd9f173cd53 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1310,6 +1310,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
 	PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT);
 	PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE);
 	PRINT_MVM_REF(IWL_MVM_REF_SENDING_CMD);
+	PRINT_MVM_REF(IWL_MVM_REF_RX);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 23d7539edf179d112e4a19cdece3b236658ad002..820f8d661e159a2fb60d1939cda27d49fde27c4a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -302,6 +302,7 @@ enum iwl_mvm_ref_type {
 	IWL_MVM_REF_FW_DBG_COLLECT,
 	IWL_MVM_REF_INIT_UCODE,
 	IWL_MVM_REF_SENDING_CMD,
+	IWL_MVM_REF_RX,
 
 	/* update debugfs.c when changing this */
 
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 58e7e4feed3a4a4a96a625900ac38913e0b396a8..ab7f7eda9c13834efa6d9fe56a9f954ad5a78fab 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -272,6 +272,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
 	u32 rate_n_flags;
 	u32 rx_pkt_status;
 	u8 crypt_len = 0;
+	bool take_ref;
 
 	phy_info = &mvm->last_phy_info;
 	rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@@ -458,8 +459,22 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
 		     ieee80211_is_probe_resp(hdr->frame_control)))
 		rx_status->boottime_ns = ktime_get_boot_ns();
 
+	/* Take a reference briefly to kick off a d0i3 entry delay so
+	 * we can handle bursts of RX packets without toggling the
+	 * state too often.  But don't do this for beacons if we are
+	 * going to idle because the beacon filtering changes we make
+	 * cause the firmware to send us collateral beacons. */
+	take_ref = !(test_bit(STATUS_TRANS_GOING_IDLE, &mvm->trans->status) &&
+		     ieee80211_is_beacon(hdr->frame_control));
+
+	if (take_ref)
+		iwl_mvm_ref(mvm, IWL_MVM_REF_RX);
+
 	iwl_mvm_pass_packet_to_mac80211(mvm, sta, napi, skb, hdr, len,
 					ampdu_status, crypt_len, rxb);
+
+	if (take_ref)
+		iwl_mvm_unref(mvm, IWL_MVM_REF_RX);
 }
 
 static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm,