From: Johannes Berg <johannes@sipsolutions.net>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org
Subject: [PATCH 07/15] mac80211: allow releasing driver-buffered frames
Date: Wed, 28 Sep 2011 14:08:56 +0200 [thread overview]
Message-ID: <20110928121130.483673519@sipsolutions.net> (raw)
In-Reply-To: 20110928120849.882884360@sipsolutions.net
From: Johannes Berg <johannes.berg@intel.com>
If there are frames for a station buffered in
the driver, mac80211 announces those in the TIM
IE but there's no way to release them. Add new
API to release such frames and use it when the
station polls for a frame.
Since the API will soon also be used for uAPSD
it is easily extensible.
Note that before this change drivers announcing
driver-buffered frames in the TIM bit actually
will respond to a PS-Poll with a potentially
lower priority frame (if there are any frames
buffered in mac80211), after this patch a driver
that hasn't been changed will no longer respond
at all. This only affects ath9k, which will need
to be fixed to implement the new API.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/mac80211.h | 31 ++++++++++++++++
net/mac80211/driver-ops.h | 15 ++++++++
net/mac80211/driver-trace.h | 35 ++++++++++++++++++
net/mac80211/sta_info.c | 82 +++++++++++++++++++++++++++++++++++---------
4 files changed, 147 insertions(+), 16 deletions(-)
--- a/net/mac80211/sta_info.c 2011-09-28 13:22:04.000000000 +0200
+++ b/net/mac80211/sta_info.c 2011-09-28 13:22:29.000000000 +0200
@@ -1147,8 +1147,10 @@ void ieee80211_sta_ps_deliver_poll_respo
struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
struct sk_buff *skb = NULL;
+ bool found = false;
bool more_data = false;
int ac;
+ unsigned long driver_release_tids = 0;
u8 ignore_for_response = sta->sta.uapsd_queues;
/*
@@ -1163,19 +1165,40 @@ void ieee80211_sta_ps_deliver_poll_respo
* Get response frame and more data bit for it.
*/
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ unsigned long tids;
+
if (ignore_for_response & BIT(ac))
continue;
- if (!skb) {
- skb = skb_dequeue(&sta->tx_filtered[ac]);
- if (!skb) {
- skb = skb_dequeue(&sta->ps_tx_buf[ac]);
+ tids = ieee80211_tids_for_ac(ac);
+
+ if (!found) {
+ driver_release_tids = sta->driver_buffered_tids & tids;
+ if (driver_release_tids) {
+ found = true;
+ } else {
+ skb = skb_dequeue(&sta->tx_filtered[ac]);
+ if (!skb) {
+ skb = skb_dequeue(&sta->ps_tx_buf[ac]);
+ if (skb)
+ local->total_ps_buffered--;
+ }
if (skb)
- local->total_ps_buffered--;
+ found = true;
}
- }
- /* FIXME: take into account driver-buffered frames */
+ /*
+ * If the driver has data on more than one TID then
+ * certainly there's more data if we release just a
+ * single frame now (from a single TID).
+ */
+ if (hweight16(driver_release_tids) > 1) {
+ more_data = true;
+ driver_release_tids =
+ BIT(ffs(driver_release_tids) - 1);
+ break;
+ }
+ }
if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
!skb_queue_empty(&sta->ps_tx_buf[ac])) {
@@ -1184,6 +1207,22 @@ void ieee80211_sta_ps_deliver_poll_respo
}
}
+ if (!found) {
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ /*
+ * FIXME: This can be the result of a race condition between
+ * us expiring a frame and the station polling for it.
+ * Should we send it a null-func frame indicating we
+ * have nothing buffered for it?
+ */
+ printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
+ "though there are no buffered frames for it\n",
+ sdata->name, sta->sta.addr);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+
+ return;
+ }
+
if (skb) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr =
@@ -1210,18 +1249,29 @@ void ieee80211_sta_ps_deliver_poll_respo
ieee80211_add_pending_skb(local, skb);
sta_info_recalc_tim(sta);
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
} else {
/*
- * FIXME: This can be the result of a race condition between
- * us expiring a frame and the station polling for it.
- * Should we send it a null-func frame indicating we
- * have nothing buffered for it?
+ * We need to release a frame that is buffered somewhere in the
+ * driver ... it'll have to handle that.
+ * Note that, as per the comment above, it'll also have to see
+ * if there is more than just one frame on the specific TID that
+ * we're releasing from, and it needs to set the more-data bit
+ * accordingly if we tell it that there's no more data. If we do
+ * tell it there's more data, then of course the more-data bit
+ * needs to be set anyway.
+ */
+ drv_release_buffered_frames(local, sta, driver_release_tids,
+ 1, IEEE80211_FRAME_RELEASE_PSPOLL,
+ more_data);
+
+ /*
+ * Note that we don't recalculate the TIM bit here as it would
+ * most likely have no effect at all unless the driver told us
+ * that the TID became empty before returning here from the
+ * release function.
+ * Either way, however, when the driver tells us that the TID
+ * became empty we'll do the TIM recalculation.
*/
- printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
- "though there are no buffered frames for it\n",
- sdata->name, sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
}
--- a/include/net/mac80211.h 2011-09-28 13:22:04.000000000 +0200
+++ b/include/net/mac80211.h 2011-09-28 13:22:29.000000000 +0200
@@ -1622,6 +1622,14 @@ enum ieee80211_tx_sync_type {
};
/**
+ * enum ieee80211_frame_release_type - frame release reason
+ * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
+ */
+enum ieee80211_frame_release_type {
+ IEEE80211_FRAME_RELEASE_PSPOLL,
+};
+
+/**
* struct ieee80211_ops - callbacks from mac80211 to the driver
*
* This structure contains various callbacks that the driver may
@@ -1931,6 +1939,23 @@ enum ieee80211_tx_sync_type {
* The callback can sleep.
* @rssi_callback: Notify driver when the average RSSI goes above/below
* thresholds that were registered previously. The callback can sleep.
+ *
+ * @release_buffered_frames: Release buffered frames according to the given
+ * parameters. In the case where the driver buffers some frames for
+ * sleeping stations mac80211 will use this callback to tell the driver
+ * to release some frames, either for PS-poll or uAPSD.
+ * Note that if the @more_data paramter is %false the driver must check
+ * if there are more frames on the given TIDs, and if there are more than
+ * the frames being released then it must still set the more-data bit in
+ * the frame. If the @more_data parameter is %true, then of course the
+ * 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 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
+ * setting the EOSP flag in the QoS header of the frames.
+ * This callback must be atomic.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2045,6 +2070,12 @@ struct ieee80211_ops {
const struct cfg80211_bitrate_mask *mask);
void (*rssi_callback)(struct ieee80211_hw *hw,
enum ieee80211_rssi_event rssi_event);
+
+ void (*release_buffered_frames)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
};
/**
--- a/net/mac80211/driver-ops.h 2011-09-28 11:44:04.000000000 +0200
+++ b/net/mac80211/driver-ops.h 2011-09-28 13:22:29.000000000 +0200
@@ -670,4 +670,19 @@ static inline void drv_rssi_callback(str
local->ops->rssi_callback(&local->hw, event);
trace_drv_return_void(local);
}
+
+static inline void
+drv_release_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_release_buffered_frames(local, &sta->sta, tids, num_frames,
+ reason, more_data);
+ if (local->ops->release_buffered_frames)
+ local->ops->release_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 11:44:04.000000000 +0200
+++ b/net/mac80211/driver-trace.h 2011-09-28 13:22:29.000000000 +0200
@@ -1129,6 +1129,41 @@ TRACE_EVENT(drv_rssi_callback,
)
);
+TRACE_EVENT(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),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ STA_ENTRY
+ __field(u16, tids)
+ __field(int, num_frames)
+ __field(int, reason)
+ __field(bool, more_data)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ STA_ASSIGN;
+ __entry->tids = tids;
+ __entry->num_frames = num_frames;
+ __entry->reason = reason;
+ __entry->more_data = more_data;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT STA_PR_FMT
+ " TIDs:0x%.4x frames:%d reason:%d more:%d",
+ LOCAL_PR_ARG, STA_PR_ARG, __entry->tids, __entry->num_frames,
+ __entry->reason, __entry->more_data
+ )
+);
+
/*
* Tracing for API calls that drivers call.
*/
next prev 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 ` Johannes Berg [this message]
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 ` [PATCH 13/15] mac80211: explicitly notify drivers of frame release Johannes Berg
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=20110928121130.483673519@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).