aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-09-29 10:04:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-30 15:57:15 -0400
commit4049e09acdf4ffd270cb8fbf1cf5b39c3d02357c (patch)
tree87aa0bc08650b5cc745733fcf422dcf871caeb43 /net/mac80211
parent8a8656fa5bbbc8568348d95184d374edb03a48b7 (diff)
mac80211: allow releasing driver-buffered frames
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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/driver-ops.h15
-rw-r--r--net/mac80211/driver-trace.h35
-rw-r--r--net/mac80211/sta_info.c82
3 files changed, 116 insertions, 16 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4f845c0845ee..8fa0d2edf54c 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -670,4 +670,19 @@ static inline void drv_rssi_callback(struct ieee80211_local *local,
670 local->ops->rssi_callback(&local->hw, event); 670 local->ops->rssi_callback(&local->hw, event);
671 trace_drv_return_void(local); 671 trace_drv_return_void(local);
672} 672}
673
674static inline void
675drv_release_buffered_frames(struct ieee80211_local *local,
676 struct sta_info *sta, u16 tids, int num_frames,
677 enum ieee80211_frame_release_type reason,
678 bool more_data)
679{
680 trace_drv_release_buffered_frames(local, &sta->sta, tids, num_frames,
681 reason, more_data);
682 if (local->ops->release_buffered_frames)
683 local->ops->release_buffered_frames(&local->hw, &sta->sta, tids,
684 num_frames, reason,
685 more_data);
686 trace_drv_return_void(local);
687}
673#endif /* __MAC80211_DRIVER_OPS */ 688#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index a46b279bbbe4..531fbd086794 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -1129,6 +1129,41 @@ TRACE_EVENT(drv_rssi_callback,
1129 ) 1129 )
1130); 1130);
1131 1131
1132TRACE_EVENT(drv_release_buffered_frames,
1133 TP_PROTO(struct ieee80211_local *local,
1134 struct ieee80211_sta *sta,
1135 u16 tids, int num_frames,
1136 enum ieee80211_frame_release_type reason,
1137 bool more_data),
1138
1139 TP_ARGS(local, sta, tids, num_frames, reason, more_data),
1140
1141 TP_STRUCT__entry(
1142 LOCAL_ENTRY
1143 STA_ENTRY
1144 __field(u16, tids)
1145 __field(int, num_frames)
1146 __field(int, reason)
1147 __field(bool, more_data)
1148 ),
1149
1150 TP_fast_assign(
1151 LOCAL_ASSIGN;
1152 STA_ASSIGN;
1153 __entry->tids = tids;
1154 __entry->num_frames = num_frames;
1155 __entry->reason = reason;
1156 __entry->more_data = more_data;
1157 ),
1158
1159 TP_printk(
1160 LOCAL_PR_FMT STA_PR_FMT
1161 " TIDs:0x%.4x frames:%d reason:%d more:%d",
1162 LOCAL_PR_ARG, STA_PR_ARG, __entry->tids, __entry->num_frames,
1163 __entry->reason, __entry->more_data
1164 )
1165);
1166
1132/* 1167/*
1133 * Tracing for API calls that drivers call. 1168 * Tracing for API calls that drivers call.
1134 */ 1169 */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 4d85672f0b8f..b3f841948c09 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1157,8 +1157,10 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
1157 struct ieee80211_sub_if_data *sdata = sta->sdata; 1157 struct ieee80211_sub_if_data *sdata = sta->sdata;
1158 struct ieee80211_local *local = sdata->local; 1158 struct ieee80211_local *local = sdata->local;
1159 struct sk_buff *skb = NULL; 1159 struct sk_buff *skb = NULL;
1160 bool found = false;
1160 bool more_data = false; 1161 bool more_data = false;
1161 int ac; 1162 int ac;
1163 unsigned long driver_release_tids = 0;
1162 u8 ignore_for_response = sta->sta.uapsd_queues; 1164 u8 ignore_for_response = sta->sta.uapsd_queues;
1163 1165
1164 /* 1166 /*
@@ -1173,19 +1175,40 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
1173 * Get response frame and more data bit for it. 1175 * Get response frame and more data bit for it.
1174 */ 1176 */
1175 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { 1177 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
1178 unsigned long tids;
1179
1176 if (ignore_for_response & BIT(ac)) 1180 if (ignore_for_response & BIT(ac))
1177 continue; 1181 continue;
1178 1182
1179 if (!skb) { 1183 tids = ieee80211_tids_for_ac(ac);
1180 skb = skb_dequeue(&sta->tx_filtered[ac]); 1184
1181 if (!skb) { 1185 if (!found) {
1182 skb = skb_dequeue(&sta->ps_tx_buf[ac]); 1186 driver_release_tids = sta->driver_buffered_tids & tids;
1187 if (driver_release_tids) {
1188 found = true;
1189 } else {
1190 skb = skb_dequeue(&sta->tx_filtered[ac]);
1191 if (!skb) {
1192 skb = skb_dequeue(&sta->ps_tx_buf[ac]);
1193 if (skb)
1194 local->total_ps_buffered--;
1195 }
1183 if (skb) 1196 if (skb)
1184 local->total_ps_buffered--; 1197 found = true;
1185 } 1198 }
1186 }
1187 1199
1188 /* FIXME: take into account driver-buffered frames */ 1200 /*
1201 * If the driver has data on more than one TID then
1202 * certainly there's more data if we release just a
1203 * single frame now (from a single TID).
1204 */
1205 if (hweight16(driver_release_tids) > 1) {
1206 more_data = true;
1207 driver_release_tids =
1208 BIT(ffs(driver_release_tids) - 1);
1209 break;
1210 }
1211 }
1189 1212
1190 if (!skb_queue_empty(&sta->tx_filtered[ac]) || 1213 if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
1191 !skb_queue_empty(&sta->ps_tx_buf[ac])) { 1214 !skb_queue_empty(&sta->ps_tx_buf[ac])) {
@@ -1194,6 +1217,22 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
1194 } 1217 }
1195 } 1218 }
1196 1219
1220 if (!found) {
1221#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
1222 /*
1223 * FIXME: This can be the result of a race condition between
1224 * us expiring a frame and the station polling for it.
1225 * Should we send it a null-func frame indicating we
1226 * have nothing buffered for it?
1227 */
1228 printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
1229 "though there are no buffered frames for it\n",
1230 sdata->name, sta->sta.addr);
1231#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
1232
1233 return;
1234 }
1235
1197 if (skb) { 1236 if (skb) {
1198 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1237 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1199 struct ieee80211_hdr *hdr = 1238 struct ieee80211_hdr *hdr =
@@ -1220,18 +1259,29 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
1220 ieee80211_add_pending_skb(local, skb); 1259 ieee80211_add_pending_skb(local, skb);
1221 1260
1222 sta_info_recalc_tim(sta); 1261 sta_info_recalc_tim(sta);
1223#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
1224 } else { 1262 } else {
1225 /* 1263 /*
1226 * FIXME: This can be the result of a race condition between 1264 * We need to release a frame that is buffered somewhere in the
1227 * us expiring a frame and the station polling for it. 1265 * driver ... it'll have to handle that.
1228 * Should we send it a null-func frame indicating we 1266 * Note that, as per the comment above, it'll also have to see
1229 * have nothing buffered for it? 1267 * if there is more than just one frame on the specific TID that
1268 * we're releasing from, and it needs to set the more-data bit
1269 * accordingly if we tell it that there's no more data. If we do
1270 * tell it there's more data, then of course the more-data bit
1271 * needs to be set anyway.
1272 */
1273 drv_release_buffered_frames(local, sta, driver_release_tids,
1274 1, IEEE80211_FRAME_RELEASE_PSPOLL,
1275 more_data);
1276
1277 /*
1278 * Note that we don't recalculate the TIM bit here as it would
1279 * most likely have no effect at all unless the driver told us
1280 * that the TID became empty before returning here from the
1281 * release function.
1282 * Either way, however, when the driver tells us that the TID
1283 * became empty we'll do the TIM recalculation.
1230 */ 1284 */
1231 printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
1232 "though there are no buffered frames for it\n",
1233 sdata->name, sta->sta.addr);
1234#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
1235 } 1285 }
1236} 1286}
1237 1287