linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Johannes Berg <johannes@sipsolutions.net>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Subject: [PATCH 13/15] mac80211: explicitly notify drivers of frame release
Date: Wed, 28 Sep 2011 14:09:02 +0200	[thread overview]
Message-ID: <20110928121132.346289879@sipsolutions.net> (raw)
In-Reply-To: 20110928120849.882884360@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-28 13:38:11.000000000 +0200
+++ b/include/net/mac80211.h	2011-09-28 14:04:35.000000000 +0200
@@ -1973,6 +1973,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);
@@ -2088,6 +2100,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-28 13:29:06.000000000 +0200
+++ b/net/mac80211/driver-ops.h	2011-09-28 14:04:35.000000000 +0200
@@ -685,4 +685,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-28 13:29:06.000000000 +0200
+++ b/net/mac80211/driver-trace.h	2011-09-28 14:04:35.000000000 +0200
@@ -1129,7 +1129,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,
@@ -1164,6 +1164,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-28 13:53:57.000000000 +0200
+++ b/net/mac80211/sta_info.c	2011-09-28 14:04:35.000000000 +0200
@@ -1159,7 +1159,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;
@@ -1200,7 +1200,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);
 	}
@@ -1217,6 +1217,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);
 }
 
@@ -1314,20 +1316,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
@@ -1347,19 +1353,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-28 12:13 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-09-28 12:08 [PATCH 00/15] mac80211 uAPSD support Johannes Berg
2011-09-28 12:08 ` [PATCH 01/15] mac80211: let drivers inform it about per TID buffered frames Johannes Berg
2011-09-28 12:08 ` [PATCH 02/15] mac80211: unify TIM bit handling Johannes Berg
2011-09-28 12:08 ` [PATCH 03/15] mac80211: also expire filtered frames Johannes Berg
2011-09-28 12:08 ` [PATCH 04/15] mac80211: split PS buffers into ACs Johannes Berg
2011-09-28 12:08 ` [PATCH 05/15] mac80211: remove return value from add_pending_skbs Johannes Berg
2011-09-28 12:08 ` [PATCH 06/15] mac80211: clear more-data bit on filtered frames Johannes Berg
2011-09-28 12:08 ` [PATCH 07/15] mac80211: allow releasing driver-buffered frames Johannes Berg
2011-09-28 12:08 ` [PATCH 08/15] mac80211: implement uAPSD Johannes Berg
2011-09-28 12:08 ` [PATCH 09/15] mac80211: send (QoS) Null if no buffered frames Johannes Berg
2011-09-28 12:08 ` [PATCH 10/15] mac80211: reply only once to each PS-poll Johannes Berg
2011-09-28 12:09 ` [PATCH 11/15] mac80211: optimise station flags Johannes Berg
2011-09-28 12:09 ` [PATCH 12/15] mac80211: add missing station flags to debugfs Johannes Berg
2011-09-28 12:09 ` Johannes Berg [this message]
2011-09-28 12:09 ` [PATCH 14/15] mac80211: allow out-of-band EOSP notification Johannes Berg
2011-09-28 12:09 ` [PATCH 15/15] mac80211: document client powersave Johannes Berg
2011-09-28 12:17 ` [PATCH 00/15] mac80211 uAPSD support Johannes Berg
2011-09-28 13:03 ` [PATCH 16/15] mac80211: don't assign seqno to or aggregate QoS Null frames 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=20110928121132.346289879@sipsolutions.net \
    --to=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).