diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dd07964ef154347f02a22ecb5db4eabe0332c55b..ee6449eff7dcb96e82301d14458a3c89cfac3588 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -370,7 +370,8 @@ struct ieee80211_bss_conf {
  * @IEEE80211_TX_STATUS_EOSP: This packet marks the end of service period,
  *	when its status is reported the service period ends. For frames in
  *	an SP that mac80211 transmits, it is already set; for driver frames
- *	the driver may set this flag.
+ *	the driver may set this flag. It is also used to do the same for
+ *	PS-Poll responses.
  *
  * Note: If you have to add new flags to the enumeration, then don't
  *	 forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
@@ -1959,6 +1960,12 @@ enum ieee80211_frame_release_type {
  *	more-data bit must always be set.
  *	The @tids parameter tells the driver which TIDs to release frames
  *	from, for PS-poll it will always have only a single bit set.
+ *	In the case this is used for a PS-poll initiated release, the
+ *	@num_frames parameter will always be 1 so code can be shared. In
+ *	this case the driver must also set %IEEE80211_TX_STATUS_EOSP flag
+ *	on the TX status (and must report TX status) so that the PS-poll
+ *	period is properly ended. This is used to avoid sending multiple
+ *	responses for a retried PS-poll frame.
  *	In the case this is used for uAPSD, the @num_frames parameter may be
  *	bigger than one, but the driver may send fewer frames (it must send
  *	at least one, however). In this case it is also responsible for
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 9a703f00b5fba11e1fccf43535a82caec7ee9406..32c8ee43f720af651199cb119ee17150b19abf39 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1194,10 +1194,12 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
 		return RX_CONTINUE;
 
 	if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
-		if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
-			ieee80211_sta_ps_deliver_poll_response(rx->sta);
-		else
-			set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
+		if (!test_sta_flags(rx->sta, WLAN_STA_SP)) {
+			if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
+				ieee80211_sta_ps_deliver_poll_response(rx->sta);
+			else
+				set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
+		}
 
 		/* Free PS Poll skb here instead of returning RX_DROP that would
 		 * count as an dropped frame. */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index d9cb56f548a9645ac115723c78e5fbd350f647a0..5732e4d0cc217b9205e783fd58c2f0752fec8d18 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1217,13 +1217,12 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
 	/*
 	 * Tell TX path to send this frame even though the
 	 * STA may still remain is PS mode after this frame
-	 * exchange.
+	 * exchange. Also set EOSP to indicate this packet
+	 * ends the poll/service period.
 	 */
-	info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE;
-
-	if (uapsd)
-		info->flags |= IEEE80211_TX_STATUS_EOSP |
-			       IEEE80211_TX_CTL_REQ_TX_STATUS;
+	info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE |
+		       IEEE80211_TX_STATUS_EOSP |
+		       IEEE80211_TX_CTL_REQ_TX_STATUS;
 
 	ieee80211_xmit(sdata, skb);
 }
@@ -1241,6 +1240,9 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
 	unsigned long driver_release_tids = 0;
 	struct sk_buff_head frames;
 
+	/* Service or PS-Poll period starts */
+	set_sta_flags(sta, WLAN_STA_SP);
+
 	__skb_queue_head_init(&frames);
 
 	/*
@@ -1357,10 +1359,11 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
 				/* set EOSP for the frame */
 				u8 *p = ieee80211_get_qos_ctl(hdr);
 				*p |= IEEE80211_QOS_CTL_EOSP;
-				info->flags |= IEEE80211_TX_STATUS_EOSP |
-					       IEEE80211_TX_CTL_REQ_TX_STATUS;
 			}
 
+			info->flags |= IEEE80211_TX_STATUS_EOSP |
+				       IEEE80211_TX_CTL_REQ_TX_STATUS;
+
 			__skb_queue_tail(&pending, skb);
 		}
 
@@ -1422,9 +1425,6 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta)
 	if (!delivery_enabled)
 		return;
 
-	/* Ohh, finally, the service period starts :-) */
-	set_sta_flags(sta, WLAN_STA_SP);
-
 	switch (sta->sta.max_sp) {
 	case 1:
 		n_frames = 2;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 751ad25f925f58600d532db92e3d9dd92c72434a..348847a326306f76bb776b93e004ebdbd8b5f9e6 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -50,7 +50,7 @@
  *	keeping station in power-save mode, reply when the driver
  *	unblocks the station.
  * @WLAN_STA_SP: Station is in a service period, so don't try to
- *	reply to other uAPSD trigger frames.
+ *	reply to other uAPSD trigger frames or PS-Poll.
  */
 enum ieee80211_sta_info_flags {
 	WLAN_STA_AUTH		= 1<<0,