aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeth Forshee2013-02-25 14:58:05 -0600
committerJohannes Berg2013-02-26 14:04:58 -0600
commita7679ed5a0e92c87eeef33ae463e39a843561836 (patch)
tree435faeb67f5eeca65a910905e967257be90a26d8
parent163df6cf292a1024277f500038fc0ed493635673 (diff)
downloadam43-linux-kernel-a7679ed5a0e92c87eeef33ae463e39a843561836.tar.gz
am43-linux-kernel-a7679ed5a0e92c87eeef33ae463e39a843561836.tar.xz
am43-linux-kernel-a7679ed5a0e92c87eeef33ae463e39a843561836.zip
mac80211: Ensure off-channel frames don't get queued
Commit 6c17b77b67587b9f9e3070fb89fe98cef3187131 (mac80211: Fix tx queue handling during scans) contains a bug that causes off-channel frames to get queued when they should be handed down to the driver for transmit. Prevent this from happening. Reported-by: Fabio Rossi <rossi.f@inwind.it> Signed-off-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/tx.c56
1 files changed, 31 insertions, 25 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index bb05a0f8603..c592a413bad 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
1231 if (local->queue_stop_reasons[q] || 1231 if (local->queue_stop_reasons[q] ||
1232 (!txpending && !skb_queue_empty(&local->pending[q]))) { 1232 (!txpending && !skb_queue_empty(&local->pending[q]))) {
1233 if (unlikely(info->flags & 1233 if (unlikely(info->flags &
1234 IEEE80211_TX_INTFL_OFFCHAN_TX_OK && 1234 IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
1235 local->queue_stop_reasons[q] & 1235 if (local->queue_stop_reasons[q] &
1236 ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { 1236 ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
1237 /*
1238 * Drop off-channel frames if queues
1239 * are stopped for any reason other
1240 * than off-channel operation. Never
1241 * queue them.
1242 */
1243 spin_unlock_irqrestore(
1244 &local->queue_stop_reason_lock,
1245 flags);
1246 ieee80211_purge_tx_queue(&local->hw,
1247 skbs);
1248 return true;
1249 }
1250 } else {
1251
1237 /* 1252 /*
1238 * Drop off-channel frames if queues are stopped 1253 * Since queue is stopped, queue up frames for
1239 * for any reason other than off-channel 1254 * later transmission from the tx-pending
1240 * operation. Never queue them. 1255 * tasklet when the queue is woken again.
1241 */ 1256 */
1242 spin_unlock_irqrestore( 1257 if (txpending)
1243 &local->queue_stop_reason_lock, flags); 1258 skb_queue_splice_init(skbs,
1244 ieee80211_purge_tx_queue(&local->hw, skbs); 1259 &local->pending[q]);
1245 return true; 1260 else
1261 skb_queue_splice_tail_init(skbs,
1262 &local->pending[q]);
1263
1264 spin_unlock_irqrestore(&local->queue_stop_reason_lock,
1265 flags);
1266 return false;
1246 } 1267 }
1247
1248 /*
1249 * Since queue is stopped, queue up frames for later
1250 * transmission from the tx-pending tasklet when the
1251 * queue is woken again.
1252 */
1253 if (txpending)
1254 skb_queue_splice_init(skbs, &local->pending[q]);
1255 else
1256 skb_queue_splice_tail_init(skbs,
1257 &local->pending[q]);
1258
1259 spin_unlock_irqrestore(&local->queue_stop_reason_lock,
1260 flags);
1261 return false;
1262 } 1268 }
1263 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); 1269 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1264 1270