From 142e3d158e288f9ec57f9b494cd7aa858940714c Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Tue, 12 Oct 2010 14:49:12 +0200 Subject: [PATCH] --- yaml --- r: 224255 b: refs/heads/master c: 2fe33e8cff354a3f320549544bffebbbab680145 h: refs/heads/master i: 224253: 11eaff6f156413ab93ffc0cc6102a432313a098e 224251: 5d4ed6ae499a170a47533e4158960b1ea72d01eb 224247: a65e85c2c0b05c48d15a8c4545aad79126cc39b8 224239: c205f9c63534c1e425ca34f95d4aa10df7359e7c 224223: a1fc8454dea080f1c068c88413b252960ab10db2 224191: 7350a39a87aee0ddcba5d386a301ac290441c074 224127: 08f548ed3f5387458ce91e8d160436867f34a2e4 223999: 643b982c4f1aac840fa7ddbecac0c6bb0cc156bc 223743: 63afd0d8de012fe33e9b9bfe9a7264d17a5abe23 223231: 3ba73eb2000ab1125a2db6928387f373e6c946b0 v: v3 --- [refs] | 2 +- trunk/drivers/net/wireless/wl12xx/wl1271_tx.c | 35 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/[refs] b/[refs] index 33de94a21338..225e98d9b42b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 25eeb9e3876a161e3afcc820c6cb72e13f9b7c7e +refs/heads/master: 2fe33e8cff354a3f320549544bffebbbab680145 diff --git a/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c b/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c index 85878e5e7526..dc3172bea0dd 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1271_tx.c @@ -212,6 +212,20 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) return enabled_rates; } +static void handle_tx_low_watermark(struct wl1271 *wl) +{ + unsigned long flags; + + if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && + skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { + /* firmware buffer has space, restart queues */ + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queues(wl->hw); + clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); + spin_unlock_irqrestore(&wl->wl_lock, flags); + } +} + void wl1271_tx_work_locked(struct wl1271 *wl) { struct sk_buff *skb; @@ -225,6 +239,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags))) { unsigned long flags; + spin_lock_irqsave(&wl->wl_lock, flags); sta_rates = wl->sta_rate_set; spin_unlock_irqrestore(&wl->wl_lock, flags); @@ -285,6 +300,7 @@ void wl1271_tx_work_locked(struct wl1271 *wl) if (sent_packets) { /* interrupt the firmware with the new packets */ wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); + handle_tx_low_watermark(wl); } out: @@ -399,19 +415,6 @@ void wl1271_tx_complete(struct wl1271 *wl) wl->tx_results_count++; } - - if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && - skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { - unsigned long flags; - - /* firmware buffer has space, restart queues */ - wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); - spin_lock_irqsave(&wl->wl_lock, flags); - ieee80211_wake_queues(wl->hw); - clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); - spin_unlock_irqrestore(&wl->wl_lock, flags); - ieee80211_queue_work(wl->hw, &wl->tx_work); - } } /* caller must hold wl->mutex */ @@ -426,6 +429,12 @@ void wl1271_tx_reset(struct wl1271 *wl) ieee80211_tx_status(wl->hw, skb); } + /* + * Make sure the driver is at a consistent state, in case this + * function is called from a context other than interface removal. + */ + handle_tx_low_watermark(wl); + for (i = 0; i < ACX_TX_DESCRIPTORS; i++) if (wl->tx_frames[i] != NULL) { skb = wl->tx_frames[i];