diff options
author | Daniel Wagner <wagi@monom.org> | 2008-07-23 13:17:01 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-08-22 16:29:49 -0400 |
commit | b9740c2396851178b99c03c2260a0adfe7f52e36 (patch) | |
tree | 98298f26d0de663a2f1c076104305c8ddf22c9f0 /drivers/net/wireless | |
parent | 8e5f3d0aaa3ae5305613553f869727b0361cd472 (diff) |
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 <wagi@monom.org>
Acked-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 43 |
1 files changed, 20 insertions, 23 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index d06507388635..4b9fde903cd6 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, | |||
37 | struct ieee80211_tx_info *rts_info; | 37 | struct ieee80211_tx_info *rts_info; |
38 | struct sk_buff *skb; | 38 | struct sk_buff *skb; |
39 | int size; | 39 | int size; |
40 | int retval = 0; | ||
40 | 41 | ||
41 | if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) | 42 | if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) |
42 | size = sizeof(struct ieee80211_cts); | 43 | size = sizeof(struct ieee80211_cts); |
@@ -44,9 +45,9 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
44 | size = sizeof(struct ieee80211_rts); | 45 | size = sizeof(struct ieee80211_rts); |
45 | 46 | ||
46 | skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom); | 47 | skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom); |
47 | if (!skb) { | 48 | if (unlikely(!skb)) { |
48 | WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); | 49 | WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); |
49 | return NETDEV_TX_BUSY; | 50 | return -ENOMEM; |
50 | } | 51 | } |
51 | 52 | ||
52 | skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); | 53 | skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); |
@@ -82,13 +83,13 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
82 | frag_skb->data, size, tx_info, | 83 | frag_skb->data, size, tx_info, |
83 | (struct ieee80211_rts *)(skb->data)); | 84 | (struct ieee80211_rts *)(skb->data)); |
84 | 85 | ||
85 | if (rt2x00queue_write_tx_frame(queue, skb)) { | 86 | retval = rt2x00queue_write_tx_frame(queue, skb); |
87 | if (retval) { | ||
86 | dev_kfree_skb_any(skb); | 88 | dev_kfree_skb_any(skb); |
87 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); | 89 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); |
88 | return NETDEV_TX_BUSY; | ||
89 | } | 90 | } |
90 | 91 | ||
91 | return NETDEV_TX_OK; | 92 | return retval; |
92 | } | 93 | } |
93 | 94 | ||
94 | int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 95 | 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) | |||
106 | * Note that we can only stop the TX queues inside the TX path | 107 | * Note that we can only stop the TX queues inside the TX path |
107 | * due to possible race conditions in mac80211. | 108 | * due to possible race conditions in mac80211. |
108 | */ | 109 | */ |
109 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) { | 110 | if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) |
110 | ieee80211_stop_queues(hw); | 111 | goto exit_fail; |
111 | dev_kfree_skb_any(skb); | ||
112 | return NETDEV_TX_OK; | ||
113 | } | ||
114 | 112 | ||
115 | /* | 113 | /* |
116 | * Determine which queue to put packet on. | 114 | * Determine which queue to put packet on. |
@@ -141,26 +139,25 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
141 | if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | | 139 | if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | |
142 | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && | 140 | IEEE80211_TX_CTL_USE_CTS_PROTECT)) && |
143 | !rt2x00dev->ops->hw->set_rts_threshold) { | 141 | !rt2x00dev->ops->hw->set_rts_threshold) { |
144 | if (rt2x00queue_available(queue) <= 1) { | 142 | if (rt2x00queue_available(queue) <= 1) |
145 | ieee80211_stop_queue(rt2x00dev->hw, qid); | 143 | goto exit_fail; |
146 | return NETDEV_TX_BUSY; | ||
147 | } | ||
148 | |||
149 | if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) { | ||
150 | ieee80211_stop_queue(rt2x00dev->hw, qid); | ||
151 | return NETDEV_TX_BUSY; | ||
152 | } | ||
153 | } | ||
154 | 144 | ||
155 | if (rt2x00queue_write_tx_frame(queue, skb)) { | 145 | if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) |
156 | ieee80211_stop_queue(rt2x00dev->hw, qid); | 146 | goto exit_fail; |
157 | return NETDEV_TX_BUSY; | ||
158 | } | 147 | } |
159 | 148 | ||
149 | if (rt2x00queue_write_tx_frame(queue, skb)) | ||
150 | goto exit_fail; | ||
151 | |||
160 | if (rt2x00queue_threshold(queue)) | 152 | if (rt2x00queue_threshold(queue)) |
161 | ieee80211_stop_queue(rt2x00dev->hw, qid); | 153 | ieee80211_stop_queue(rt2x00dev->hw, qid); |
162 | 154 | ||
163 | return NETDEV_TX_OK; | 155 | return NETDEV_TX_OK; |
156 | |||
157 | exit_fail: | ||
158 | ieee80211_stop_queue(rt2x00dev->hw, qid); | ||
159 | dev_kfree_skb_any(skb); | ||
160 | return NETDEV_TX_OK; | ||
164 | } | 161 | } |
165 | EXPORT_SYMBOL_GPL(rt2x00mac_tx); | 162 | EXPORT_SYMBOL_GPL(rt2x00mac_tx); |
166 | 163 | ||