Commit f8e79ddd authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville

mac80211: fix fragmentation kludge

This patch make mac80211 transmit correctly fragmented packet after
queue was stopped
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent dc1968e7
...@@ -586,6 +586,7 @@ struct ieee80211_local { ...@@ -586,6 +586,7 @@ struct ieee80211_local {
struct timer_list sta_cleanup; struct timer_list sta_cleanup;
unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES];
struct tasklet_struct tx_pending_tasklet; struct tasklet_struct tx_pending_tasklet;
......
...@@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, ...@@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_tx_data *tx) struct ieee80211_tx_data *tx)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info;
int ret, i; int ret, i;
if (netif_subqueue_stopped(local->mdev, skb))
return IEEE80211_TX_AGAIN;
if (skb) { if (skb) {
if (netif_subqueue_stopped(local->mdev, skb))
return IEEE80211_TX_AGAIN;
info = IEEE80211_SKB_CB(skb);
ieee80211_dump_frame(wiphy_name(local->hw.wiphy), ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
"TX to low-level driver", skb); "TX to low-level driver", skb);
ret = local->ops->tx(local_to_hw(local), skb); ret = local->ops->tx(local_to_hw(local), skb);
...@@ -1215,6 +1216,7 @@ retry: ...@@ -1215,6 +1216,7 @@ retry:
if (ret == IEEE80211_TX_FRAG_AGAIN) if (ret == IEEE80211_TX_FRAG_AGAIN)
skb = NULL; skb = NULL;
set_bit(queue, local->queues_pending); set_bit(queue, local->queues_pending);
smp_mb(); smp_mb();
/* /*
...@@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data) ...@@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data)
netif_tx_lock_bh(dev); netif_tx_lock_bh(dev);
for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) {
/* Check that this queue is ok */ /* Check that this queue is ok */
if (__netif_subqueue_stopped(local->mdev, i)) if (__netif_subqueue_stopped(local->mdev, i) &&
!test_bit(i, local->queues_pending_run))
continue; continue;
if (!test_bit(i, local->queues_pending)) { if (!test_bit(i, local->queues_pending)) {
clear_bit(i, local->queues_pending_run);
ieee80211_wake_queue(&local->hw, i); ieee80211_wake_queue(&local->hw, i);
continue; continue;
} }
clear_bit(i, local->queues_pending_run);
netif_start_subqueue(local->mdev, i);
store = &local->pending_packet[i]; store = &local->pending_packet[i];
tx.extra_frag = store->extra_frag; tx.extra_frag = store->extra_frag;
tx.num_extra_frag = store->num_extra_frag; tx.num_extra_frag = store->num_extra_frag;
......
...@@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) ...@@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
if (test_bit(queue, local->queues_pending)) { if (test_bit(queue, local->queues_pending)) {
set_bit(queue, local->queues_pending_run);
tasklet_schedule(&local->tx_pending_tasklet); tasklet_schedule(&local->tx_pending_tasklet);
} else { } else {
netif_wake_subqueue(local->mdev, queue); netif_wake_subqueue(local->mdev, queue);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment