From b9740c2396851178b99c03c2260a0adfe7f52e36 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 23 Jul 2008 19:17:01 +0200 Subject: rt2x00mac: In error case stop netdev queue, free skb and return NETDEV_TX_OK It is not allowed to use NETDEV_TX_BUSY in tx path anymore. Signed-off-by: Daniel Wagner Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 43 +++++++++++++++------------------ 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless/rt2x00') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index d0650738863..4b9fde903cd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -37,6 +37,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_info *rts_info; struct sk_buff *skb; int size; + int retval = 0; if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) size = sizeof(struct ieee80211_cts); @@ -44,9 +45,9 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, size = sizeof(struct ieee80211_rts); skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom); - if (!skb) { + if (unlikely(!skb)) { WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); - return NETDEV_TX_BUSY; + return -ENOMEM; } skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); @@ -82,13 +83,13 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, frag_skb->data, size, tx_info, (struct ieee80211_rts *)(skb->data)); - if (rt2x00queue_write_tx_frame(queue, skb)) { + retval = rt2x00queue_write_tx_frame(queue, skb); + if (retval) { dev_kfree_skb_any(skb); WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); - return NETDEV_TX_BUSY; } - return NETDEV_TX_OK; + return retval; } int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) @@ -106,11 +107,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) * Note that we can only stop the TX queues inside the TX path * due to possible race conditions in mac80211. */ - if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) { - ieee80211_stop_queues(hw); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } + if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) + goto exit_fail; /* * Determine which queue to put packet on. @@ -141,26 +139,25 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && !rt2x00dev->ops->hw->set_rts_threshold) { - if (rt2x00queue_available(queue) <= 1) { - ieee80211_stop_queue(rt2x00dev->hw, qid); - return NETDEV_TX_BUSY; - } - - if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) { - ieee80211_stop_queue(rt2x00dev->hw, qid); - return NETDEV_TX_BUSY; - } - } + if (rt2x00queue_available(queue) <= 1) + goto exit_fail; - if (rt2x00queue_write_tx_frame(queue, skb)) { - ieee80211_stop_queue(rt2x00dev->hw, qid); - return NETDEV_TX_BUSY; + if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) + goto exit_fail; } + if (rt2x00queue_write_tx_frame(queue, skb)) + goto exit_fail; + if (rt2x00queue_threshold(queue)) ieee80211_stop_queue(rt2x00dev->hw, qid); return NETDEV_TX_OK; + + exit_fail: + ieee80211_stop_queue(rt2x00dev->hw, qid); + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } EXPORT_SYMBOL_GPL(rt2x00mac_tx); -- cgit v1.2.3-70-g09d2