aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDaniel Wagner <wagi@monom.org>2008-07-23 13:17:01 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 16:29:49 -0400
commitb9740c2396851178b99c03c2260a0adfe7f52e36 (patch)
tree98298f26d0de663a2f1c076104305c8ddf22c9f0 /drivers/net
parent8e5f3d0aaa3ae5305613553f869727b0361cd472 (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')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c43
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
94int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 95int 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}
165EXPORT_SYMBOL_GPL(rt2x00mac_tx); 162EXPORT_SYMBOL_GPL(rt2x00mac_tx);
166 163