aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-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