All of lore.kernel.org
 help / color / mirror / Atom feed
From: Johannes Berg <johannes@sipsolutions.net>
To: linux-wireless@vger.kernel.org
Subject: [RFC 13/15] mac80211: explicitly notify drivers of frame release
Date: Thu, 22 Sep 2011 17:47:39 +0200	[thread overview]
Message-ID: <20110922154852.131981800@sipsolutions.net> (raw)
In-Reply-To: 20110922154726.521122680@sipsolutions.net

From: Johannes Berg <johannes.berg@intel.com>

iwlwifi needs to know the number of frames that are
going to be sent to a station while it is asleep so
it can properly handle the uCode blocking of that
station.

Before uAPSD, we got by by telling the device that
a single frame was going to be released whenever we
encountered IEEE80211_TX_CTL_POLL_RESPONSE. With
uAPSD, however, that is no longer possible since
there could be more than a single frame.

To support this model, add a new callback to notify
drivers when frames are going to be released.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h      |   17 +++++++++++++++++
 net/mac80211/driver-ops.h   |   15 +++++++++++++++
 net/mac80211/driver-trace.h |   22 +++++++++++++++++++++-
 net/mac80211/sta_info.c     |   34 +++++++++++++++++++++++++---------
 4 files changed, 78 insertions(+), 10 deletions(-)

--- a/include/net/mac80211.h	2011-09-22 17:16:25.000000000 +0200
+++ b/include/net/mac80211.h	2011-09-22 17:16:55.000000000 +0200
@@ -1969,6 +1969,18 @@ enum ieee80211_frame_release_type {
  *	service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP
  *	on the last frame in the SP.
  *	This callback must be atomic.
+ * @allow_buffered_frames: Prepare device to allow the given number of frames
+ *	to go out to the given station. The frames will be sent by mac80211
+ *	via the usual TX path after this call. The TX information for frames
+ *	released will also have the %IEEE80211_TX_CTL_POLL_RESPONSE flag set
+ *	and the last one will also have %IEEE80211_TX_STATUS_EOSP set. In case
+ *	frames from multiple TIDs are released and the driver might reorder
+ *	them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag
+ *	on the last frame and clear it on all others and also handle the EOSP
+ *	bit in the QoS header correctly.
+ *	The @tids parameter is a bitmap and tells the driver which TIDs the
+ *	frames will be on; it will at most have two bits set.
+ *	This callback must be atomic.
  */
 struct ieee80211_ops {
 	void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2083,6 +2095,11 @@ struct ieee80211_ops {
 	void (*rssi_callback)(struct ieee80211_hw *hw,
 			      enum ieee80211_rssi_event rssi_event);
 
+	void (*allow_buffered_frames)(struct ieee80211_hw *hw,
+				      struct ieee80211_sta *sta,
+				      u16 tids, int num_frames,
+				      enum ieee80211_frame_release_type reason,
+				      bool more_data);
 	void (*release_buffered_frames)(struct ieee80211_hw *hw,
 					struct ieee80211_sta *sta,
 					u16 tids, int num_frames,
--- a/net/mac80211/driver-ops.h	2011-09-22 17:12:55.000000000 +0200
+++ b/net/mac80211/driver-ops.h	2011-09-22 17:16:55.000000000 +0200
@@ -680,4 +680,19 @@ drv_release_buffered_frames(struct ieee8
 						    more_data);
 	trace_drv_return_void(local);
 }
+
+static inline void
+drv_allow_buffered_frames(struct ieee80211_local *local,
+			  struct sta_info *sta, u16 tids, int num_frames,
+			  enum ieee80211_frame_release_type reason,
+			  bool more_data)
+{
+	trace_drv_allow_buffered_frames(local, &sta->sta, tids, num_frames,
+					reason, more_data);
+	if (local->ops->allow_buffered_frames)
+		local->ops->allow_buffered_frames(&local->hw, &sta->sta,
+						  tids, num_frames, reason,
+						  more_data);
+	trace_drv_return_void(local);
+}
 #endif /* __MAC80211_DRIVER_OPS */
--- a/net/mac80211/driver-trace.h	2011-09-22 17:12:55.000000000 +0200
+++ b/net/mac80211/driver-trace.h	2011-09-22 17:16:55.000000000 +0200
@@ -1117,7 +1117,7 @@ TRACE_EVENT(drv_rssi_callback,
 	)
 );
 
-TRACE_EVENT(drv_release_buffered_frames,
+DECLARE_EVENT_CLASS(release_evt,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sta *sta,
 		 u16 tids, int num_frames,
@@ -1152,6 +1152,26 @@ TRACE_EVENT(drv_release_buffered_frames,
 	)
 );
 
+DEFINE_EVENT(release_evt, drv_release_buffered_frames,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sta *sta,
+		 u16 tids, int num_frames,
+		 enum ieee80211_frame_release_type reason,
+		 bool more_data),
+
+	TP_ARGS(local, sta, tids, num_frames, reason, more_data)
+);
+
+DEFINE_EVENT(release_evt, drv_allow_buffered_frames,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sta *sta,
+		 u16 tids, int num_frames,
+		 enum ieee80211_frame_release_type reason,
+		 bool more_data),
+
+	TP_ARGS(local, sta, tids, num_frames, reason, more_data)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
--- a/net/mac80211/sta_info.c	2011-09-22 17:16:51.000000000 +0200
+++ b/net/mac80211/sta_info.c	2011-09-22 17:19:55.000000000 +0200
@@ -1157,7 +1157,7 @@ void ieee80211_sta_ps_deliver_wakeup(str
 
 static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata,
 					 struct sta_info *sta, int tid,
-					 bool uapsd)
+					 enum ieee80211_frame_release_type reason)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_qos_hdr *nullfunc;
@@ -1198,7 +1198,7 @@ static void ieee80211_send_null_response
 
 		nullfunc->qos_ctrl = cpu_to_le16(tid);
 
-		if (uapsd)
+		if (reason == IEEE80211_FRAME_RELEASE_UAPSD)
 			nullfunc->qos_ctrl |=
 				cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
 	}
@@ -1215,6 +1215,8 @@ static void ieee80211_send_null_response
 		       IEEE80211_TX_STATUS_EOSP |
 		       IEEE80211_TX_CTL_REQ_TX_STATUS;
 
+	drv_allow_buffered_frames(local, sta, BIT(tid), 1, reason, false);
+
 	ieee80211_xmit(sdata, skb);
 }
 
@@ -1312,20 +1314,24 @@ ieee80211_sta_ps_deliver_response(struct
 		/* This will evaluate to 1, 3, 5 or 7. */
 		tid = 7 - ((ffs(~ignored_acs) - 1) << 1);
 
-		ieee80211_send_null_response(sdata, sta, tid,
-				reason == IEEE80211_FRAME_RELEASE_UAPSD);
+		ieee80211_send_null_response(sdata, sta, tid, reason);
 		return;
 	}
 
 	if (!driver_release_tids) {
 		struct sk_buff_head pending;
 		struct sk_buff *skb;
+		int num = 0;
+		u16 tids = 0;
 
 		skb_queue_head_init(&pending);
 
 		while ((skb = __skb_dequeue(&frames))) {
 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 			struct ieee80211_hdr *hdr = (void *) skb->data;
+			u8 *qoshdr = NULL;
+
+			num++;
 
 			/*
 			 * Tell TX path to send this frame even though the
@@ -1345,19 +1351,29 @@ ieee80211_sta_ps_deliver_response(struct
 				hdr->frame_control |=
 					cpu_to_le16(IEEE80211_FCTL_MOREDATA);
 
+			if (ieee80211_is_data_qos(hdr->frame_control) ||
+			    ieee80211_is_qos_nullfunc(hdr->frame_control))
+				qoshdr = ieee80211_get_qos_ctl(hdr);
+
+			/* set EOSP for the frame */
 			if (reason == IEEE80211_FRAME_RELEASE_UAPSD &&
-			    skb_queue_empty(&frames)) {
-				/* set EOSP for the frame */
-				u8 *p = ieee80211_get_qos_ctl(hdr);
-				*p |= IEEE80211_QOS_CTL_EOSP;
-			}
+			    qoshdr && skb_queue_empty(&frames))
+				*qoshdr |= IEEE80211_QOS_CTL_EOSP;
 
 			info->flags |= IEEE80211_TX_STATUS_EOSP |
 				       IEEE80211_TX_CTL_REQ_TX_STATUS;
 
+			if (qoshdr)
+				tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK);
+			else
+				tids |= BIT(0);
+
 			__skb_queue_tail(&pending, skb);
 		}
 
+		drv_allow_buffered_frames(local, sta, tids, num,
+					  reason, more_data);
+
 		ieee80211_add_pending_skbs(local, &pending);
 
 		sta_info_recalc_tim(sta);



  parent reply	other threads:[~2011-09-22 15:50 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-22 15:47 [RFC 00/15] mac80211 uAPSD support Johannes Berg
2011-09-22 15:47 ` [RFC 01/15] mac80211: let drivers inform it about per TID buffered frames Johannes Berg
2011-09-22 15:47 ` [RFC 02/15] mac80211: unify TIM bit handling Johannes Berg
2011-09-22 15:47 ` [RFC 03/15] mac80211: also expire filtered frames Johannes Berg
2011-09-26 22:30   ` Luis R. Rodriguez
2011-09-27  2:26     ` Adrian Chadd
2011-09-27  7:50       ` Johannes Berg
2011-09-27 12:24         ` Adrian Chadd
2011-09-27 12:25           ` Adrian Chadd
2011-09-27  7:47     ` Johannes Berg
2011-09-22 15:47 ` [RFC 04/15] mac80211: split PS buffers into ACs Johannes Berg
2011-09-27 20:51   ` Luis R. Rodriguez
2011-09-28  7:10     ` Johannes Berg
2011-09-22 15:47 ` [RFC 05/15] mac80211: remove return value from add_pending_skbs Johannes Berg
2011-09-22 15:47 ` [RFC 06/15] mac80211: clear more-data bit on filtered frames Johannes Berg
2011-09-22 15:47 ` [RFC 07/15] mac80211: allow releasing driver-buffered frames Johannes Berg
2011-09-22 15:47 ` [RFC 08/15] mac80211: implement uAPSD Johannes Berg
2011-09-22 15:47 ` [RFC 09/15] mac80211: send (QoS) Null if no buffered frames Johannes Berg
2011-09-22 15:47 ` [RFC 10/15] mac80211: reply only once to each PS-poll Johannes Berg
2011-09-22 15:47 ` [RFC 11/15] mac80211: optimise station flags Johannes Berg
2011-09-22 15:47 ` [RFC 12/15] mac80211: add missing station flags to debugfs Johannes Berg
2011-09-22 15:47 ` Johannes Berg [this message]
2011-09-22 15:47 ` [RFC 14/15] mac80211: allow out-of-band EOSP notification Johannes Berg
2011-09-22 15:47 ` [RFC 15/15] mac80211: document client powersave Johannes Berg
2011-09-22 15:52 ` [RFC 00/15] mac80211 uAPSD support Johannes Berg
2011-09-22 23:25   ` Luis R. Rodriguez
2011-09-23  8:59     ` Johannes Berg
2011-09-23 18:06 ` Dmitry Tarnyagin
2011-09-23 18:14   ` Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20110922154852.131981800@sipsolutions.net \
    --to=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.