aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-07-08 11:03:36 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-08 11:03:36 -0400
commit204d1641d200709c759d8c269458cbc7de378c40 (patch)
treece88690b4422078883f1651537ccd1f5d8ed7258 /drivers/net/wireless/rt2x00
parent31817df025e24559a01d33ddd68bd11b21bf9d7b (diff)
parent5f0dd296a01c8173fcc05a8b262a1168ae90bc74 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c108
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c1
13 files changed, 94 insertions, 52 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 937f9e8bf05f..76bcc3547976 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1723,6 +1723,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
1723 .set_antenna = rt2x00mac_set_antenna, 1723 .set_antenna = rt2x00mac_set_antenna,
1724 .get_antenna = rt2x00mac_get_antenna, 1724 .get_antenna = rt2x00mac_get_antenna,
1725 .get_ringparam = rt2x00mac_get_ringparam, 1725 .get_ringparam = rt2x00mac_get_ringparam,
1726 .tx_frames_pending = rt2x00mac_tx_frames_pending,
1726}; 1727};
1727 1728
1728static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { 1729static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index d27d7b8ba3b6..c288d951c034 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -2016,6 +2016,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
2016 .set_antenna = rt2x00mac_set_antenna, 2016 .set_antenna = rt2x00mac_set_antenna,
2017 .get_antenna = rt2x00mac_get_antenna, 2017 .get_antenna = rt2x00mac_get_antenna,
2018 .get_ringparam = rt2x00mac_get_ringparam, 2018 .get_ringparam = rt2x00mac_get_ringparam,
2019 .tx_frames_pending = rt2x00mac_tx_frames_pending,
2019}; 2020};
2020 2021
2021static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { 2022static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 15237c275486..53c5f878f61d 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1827,6 +1827,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
1827 .set_antenna = rt2x00mac_set_antenna, 1827 .set_antenna = rt2x00mac_set_antenna,
1828 .get_antenna = rt2x00mac_get_antenna, 1828 .get_antenna = rt2x00mac_get_antenna,
1829 .get_ringparam = rt2x00mac_get_ringparam, 1829 .get_ringparam = rt2x00mac_get_ringparam,
1830 .tx_frames_pending = rt2x00mac_tx_frames_pending,
1830}; 1831};
1831 1832
1832static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { 1833static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 9ccc53733bae..ebc17ad61dec 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1031,6 +1031,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
1031 .flush = rt2x00mac_flush, 1031 .flush = rt2x00mac_flush,
1032 .get_survey = rt2800_get_survey, 1032 .get_survey = rt2800_get_survey,
1033 .get_ringparam = rt2x00mac_get_ringparam, 1033 .get_ringparam = rt2x00mac_get_ringparam,
1034 .tx_frames_pending = rt2x00mac_tx_frames_pending,
1034}; 1035};
1035 1036
1036static const struct rt2800_ops rt2800pci_rt2800_ops = { 1037static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -1160,6 +1161,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
1160#endif 1161#endif
1161#ifdef CONFIG_RT2800PCI_RT53XX 1162#ifdef CONFIG_RT2800PCI_RT53XX
1162 { PCI_DEVICE(0x1814, 0x5390) }, 1163 { PCI_DEVICE(0x1814, 0x5390) },
1164 { PCI_DEVICE(0x1814, 0x539f) },
1163#endif 1165#endif
1164 { 0, } 1166 { 0, }
1165}; 1167};
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6e9229830a29..59e77797c0fa 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -757,6 +757,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
757 .flush = rt2x00mac_flush, 757 .flush = rt2x00mac_flush,
758 .get_survey = rt2800_get_survey, 758 .get_survey = rt2800_get_survey,
759 .get_ringparam = rt2x00mac_get_ringparam, 759 .get_ringparam = rt2x00mac_get_ringparam,
760 .tx_frames_pending = rt2x00mac_tx_frames_pending,
760}; 761};
761 762
762static const struct rt2800_ops rt2800usb_rt2800_ops = { 763static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -1020,6 +1021,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
1020 { USB_DEVICE(0x0df6, 0x0048) }, 1021 { USB_DEVICE(0x0df6, 0x0048) },
1021 { USB_DEVICE(0x0df6, 0x0051) }, 1022 { USB_DEVICE(0x0df6, 0x0051) },
1022 { USB_DEVICE(0x0df6, 0x005f) }, 1023 { USB_DEVICE(0x0df6, 0x005f) },
1024 { USB_DEVICE(0x0df6, 0x0060) },
1023 /* SMC */ 1025 /* SMC */
1024 { USB_DEVICE(0x083a, 0x6618) }, 1026 { USB_DEVICE(0x083a, 0x6618) },
1025 { USB_DEVICE(0x083a, 0x7511) }, 1027 { USB_DEVICE(0x083a, 0x7511) },
@@ -1076,6 +1078,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
1076 { USB_DEVICE(0x148f, 0x3572) }, 1078 { USB_DEVICE(0x148f, 0x3572) },
1077 /* Sitecom */ 1079 /* Sitecom */
1078 { USB_DEVICE(0x0df6, 0x0041) }, 1080 { USB_DEVICE(0x0df6, 0x0041) },
1081 { USB_DEVICE(0x0df6, 0x0062) },
1079 /* Toshiba */ 1082 /* Toshiba */
1080 { USB_DEVICE(0x0930, 0x0a07) }, 1083 { USB_DEVICE(0x0930, 0x0a07) },
1081 /* Zinwell */ 1084 /* Zinwell */
@@ -1174,8 +1177,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
1174 { USB_DEVICE(0x0df6, 0x004a) }, 1177 { USB_DEVICE(0x0df6, 0x004a) },
1175 { USB_DEVICE(0x0df6, 0x004d) }, 1178 { USB_DEVICE(0x0df6, 0x004d) },
1176 { USB_DEVICE(0x0df6, 0x0053) }, 1179 { USB_DEVICE(0x0df6, 0x0053) },
1177 { USB_DEVICE(0x0df6, 0x0060) },
1178 { USB_DEVICE(0x0df6, 0x0062) },
1179 /* SMC */ 1180 /* SMC */
1180 { USB_DEVICE(0x083a, 0xa512) }, 1181 { USB_DEVICE(0x083a, 0xa512) },
1181 { USB_DEVICE(0x083a, 0xc522) }, 1182 { USB_DEVICE(0x083a, 0xc522) },
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 4efaf886fb89..f82bfeb79ebb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1277,6 +1277,7 @@ int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
1277int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); 1277int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
1278void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, 1278void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
1279 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); 1279 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
1280bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);
1280 1281
1281/* 1282/*
1282 * Driver allocation handlers. 1283 * Driver allocation handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 1bb9d46077ff..1ca4c7ffc189 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -45,11 +45,11 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
45 } 45 }
46} 46}
47 47
48void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, 48void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
49 struct sk_buff *skb,
49 struct txentry_desc *txdesc) 50 struct txentry_desc *txdesc)
50{ 51{
51 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 52 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
52 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
53 struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; 53 struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
54 54
55 if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key) 55 if (!test_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags) || !hw_key)
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 322cc4f3de5d..15cdc7e57fc4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -336,7 +336,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
336 */ 336 */
337#ifdef CONFIG_RT2X00_LIB_CRYPTO 337#ifdef CONFIG_RT2X00_LIB_CRYPTO
338enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key); 338enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
339void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, 339void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
340 struct sk_buff *skb,
340 struct txentry_desc *txdesc); 341 struct txentry_desc *txdesc);
341unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, 342unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,
342 struct sk_buff *skb); 343 struct sk_buff *skb);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 93bec140e598..8efab3983528 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -818,3 +818,17 @@ void rt2x00mac_get_ringparam(struct ieee80211_hw *hw,
818 *rx_max = rt2x00dev->rx->limit; 818 *rx_max = rt2x00dev->rx->limit;
819} 819}
820EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam); 820EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam);
821
822bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw)
823{
824 struct rt2x00_dev *rt2x00dev = hw->priv;
825 struct data_queue *queue;
826
827 tx_queue_for_each(rt2x00dev, queue) {
828 if (!rt2x00queue_empty(queue))
829 return true;
830 }
831
832 return false;
833}
834EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index c7fc9def6bcf..29edb9fbe6f1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -200,11 +200,12 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
200 skb_pull(skb, l2pad); 200 skb_pull(skb, l2pad);
201} 201}
202 202
203static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, 203static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev,
204 struct sk_buff *skb,
204 struct txentry_desc *txdesc) 205 struct txentry_desc *txdesc)
205{ 206{
206 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); 207 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
207 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; 208 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
208 struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); 209 struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
209 210
210 if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) 211 if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
@@ -212,7 +213,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
212 213
213 __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); 214 __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
214 215
215 if (!test_bit(REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->cap_flags)) 216 if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags))
216 return; 217 return;
217 218
218 /* 219 /*
@@ -237,12 +238,12 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
237 238
238} 239}
239 240
240static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, 241static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev,
242 struct sk_buff *skb,
241 struct txentry_desc *txdesc, 243 struct txentry_desc *txdesc,
242 const struct rt2x00_rate *hwrate) 244 const struct rt2x00_rate *hwrate)
243{ 245{
244 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 246 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
245 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
246 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; 247 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
247 unsigned int data_length; 248 unsigned int data_length;
248 unsigned int duration; 249 unsigned int duration;
@@ -259,8 +260,8 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
259 txdesc->u.plcp.ifs = IFS_SIFS; 260 txdesc->u.plcp.ifs = IFS_SIFS;
260 261
261 /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */ 262 /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
262 data_length = entry->skb->len + 4; 263 data_length = skb->len + 4;
263 data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb); 264 data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
264 265
265 /* 266 /*
266 * PLCP setup 267 * PLCP setup
@@ -301,13 +302,14 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
301 } 302 }
302} 303}
303 304
304static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry, 305static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev,
306 struct sk_buff *skb,
305 struct txentry_desc *txdesc, 307 struct txentry_desc *txdesc,
306 const struct rt2x00_rate *hwrate) 308 const struct rt2x00_rate *hwrate)
307{ 309{
308 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); 310 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
309 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; 311 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
310 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; 312 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
311 313
312 if (tx_info->control.sta) 314 if (tx_info->control.sta)
313 txdesc->u.ht.mpdu_density = 315 txdesc->u.ht.mpdu_density =
@@ -380,12 +382,12 @@ static void rt2x00queue_create_tx_descriptor_ht(struct queue_entry *entry,
380 txdesc->u.ht.txop = TXOP_HTTXOP; 382 txdesc->u.ht.txop = TXOP_HTTXOP;
381} 383}
382 384
383static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, 385static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev,
386 struct sk_buff *skb,
384 struct txentry_desc *txdesc) 387 struct txentry_desc *txdesc)
385{ 388{
386 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 389 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
387 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); 390 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
388 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
389 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; 391 struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
390 struct ieee80211_rate *rate; 392 struct ieee80211_rate *rate;
391 const struct rt2x00_rate *hwrate = NULL; 393 const struct rt2x00_rate *hwrate = NULL;
@@ -395,8 +397,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
395 /* 397 /*
396 * Header and frame information. 398 * Header and frame information.
397 */ 399 */
398 txdesc->length = entry->skb->len; 400 txdesc->length = skb->len;
399 txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); 401 txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);
400 402
401 /* 403 /*
402 * Check whether this frame is to be acked. 404 * Check whether this frame is to be acked.
@@ -471,13 +473,15 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
471 /* 473 /*
472 * Apply TX descriptor handling by components 474 * Apply TX descriptor handling by components
473 */ 475 */
474 rt2x00crypto_create_tx_descriptor(entry, txdesc); 476 rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc);
475 rt2x00queue_create_tx_descriptor_seq(entry, txdesc); 477 rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc);
476 478
477 if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) 479 if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags))
478 rt2x00queue_create_tx_descriptor_ht(entry, txdesc, hwrate); 480 rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc,
481 hwrate);
479 else 482 else
480 rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); 483 rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc,
484 hwrate);
481} 485}
482 486
483static int rt2x00queue_write_tx_data(struct queue_entry *entry, 487static int rt2x00queue_write_tx_data(struct queue_entry *entry,
@@ -555,33 +559,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
555 bool local) 559 bool local)
556{ 560{
557 struct ieee80211_tx_info *tx_info; 561 struct ieee80211_tx_info *tx_info;
558 struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); 562 struct queue_entry *entry;
559 struct txentry_desc txdesc; 563 struct txentry_desc txdesc;
560 struct skb_frame_desc *skbdesc; 564 struct skb_frame_desc *skbdesc;
561 u8 rate_idx, rate_flags; 565 u8 rate_idx, rate_flags;
562 566 int ret = 0;
563 if (unlikely(rt2x00queue_full(queue))) {
564 ERROR(queue->rt2x00dev,
565 "Dropping frame due to full tx queue %d.\n", queue->qid);
566 return -ENOBUFS;
567 }
568
569 if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
570 &entry->flags))) {
571 ERROR(queue->rt2x00dev,
572 "Arrived at non-free entry in the non-full queue %d.\n"
573 "Please file bug report to %s.\n",
574 queue->qid, DRV_PROJECT);
575 return -EINVAL;
576 }
577 567
578 /* 568 /*
579 * Copy all TX descriptor information into txdesc, 569 * Copy all TX descriptor information into txdesc,
580 * after that we are free to use the skb->cb array 570 * after that we are free to use the skb->cb array
581 * for our information. 571 * for our information.
582 */ 572 */
583 entry->skb = skb; 573 rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc);
584 rt2x00queue_create_tx_descriptor(entry, &txdesc);
585 574
586 /* 575 /*
587 * All information is retrieved from the skb->cb array, 576 * All information is retrieved from the skb->cb array,
@@ -593,7 +582,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
593 rate_flags = tx_info->control.rates[0].flags; 582 rate_flags = tx_info->control.rates[0].flags;
594 skbdesc = get_skb_frame_desc(skb); 583 skbdesc = get_skb_frame_desc(skb);
595 memset(skbdesc, 0, sizeof(*skbdesc)); 584 memset(skbdesc, 0, sizeof(*skbdesc));
596 skbdesc->entry = entry;
597 skbdesc->tx_rate_idx = rate_idx; 585 skbdesc->tx_rate_idx = rate_idx;
598 skbdesc->tx_rate_flags = rate_flags; 586 skbdesc->tx_rate_flags = rate_flags;
599 587
@@ -622,9 +610,33 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
622 * for PCI devices. 610 * for PCI devices.
623 */ 611 */
624 if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags)) 612 if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags))
625 rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); 613 rt2x00queue_insert_l2pad(skb, txdesc.header_length);
626 else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags)) 614 else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags))
627 rt2x00queue_align_frame(entry->skb); 615 rt2x00queue_align_frame(skb);
616
617 spin_lock(&queue->tx_lock);
618
619 if (unlikely(rt2x00queue_full(queue))) {
620 ERROR(queue->rt2x00dev,
621 "Dropping frame due to full tx queue %d.\n", queue->qid);
622 ret = -ENOBUFS;
623 goto out;
624 }
625
626 entry = rt2x00queue_get_entry(queue, Q_INDEX);
627
628 if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
629 &entry->flags))) {
630 ERROR(queue->rt2x00dev,
631 "Arrived at non-free entry in the non-full queue %d.\n"
632 "Please file bug report to %s.\n",
633 queue->qid, DRV_PROJECT);
634 ret = -EINVAL;
635 goto out;
636 }
637
638 skbdesc->entry = entry;
639 entry->skb = skb;
628 640
629 /* 641 /*
630 * It could be possible that the queue was corrupted and this 642 * It could be possible that the queue was corrupted and this
@@ -634,7 +646,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
634 if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) { 646 if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
635 clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); 647 clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
636 entry->skb = NULL; 648 entry->skb = NULL;
637 return -EIO; 649 ret = -EIO;
650 goto out;
638 } 651 }
639 652
640 set_bit(ENTRY_DATA_PENDING, &entry->flags); 653 set_bit(ENTRY_DATA_PENDING, &entry->flags);
@@ -643,7 +656,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
643 rt2x00queue_write_tx_descriptor(entry, &txdesc); 656 rt2x00queue_write_tx_descriptor(entry, &txdesc);
644 rt2x00queue_kick_tx_queue(queue, &txdesc); 657 rt2x00queue_kick_tx_queue(queue, &txdesc);
645 658
646 return 0; 659out:
660 spin_unlock(&queue->tx_lock);
661 return ret;
647} 662}
648 663
649int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, 664int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
@@ -697,7 +712,7 @@ int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
697 * after that we are free to use the skb->cb array 712 * after that we are free to use the skb->cb array
698 * for our information. 713 * for our information.
699 */ 714 */
700 rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); 715 rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc);
701 716
702 /* 717 /*
703 * Fill in skb descriptor 718 * Fill in skb descriptor
@@ -1184,6 +1199,7 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
1184 struct data_queue *queue, enum data_queue_qid qid) 1199 struct data_queue *queue, enum data_queue_qid qid)
1185{ 1200{
1186 mutex_init(&queue->status_lock); 1201 mutex_init(&queue->status_lock);
1202 spin_lock_init(&queue->tx_lock);
1187 spin_lock_init(&queue->index_lock); 1203 spin_lock_init(&queue->index_lock);
1188 1204
1189 queue->rt2x00dev = rt2x00dev; 1205 queue->rt2x00dev = rt2x00dev;
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 590047499e3c..f2100f4ddcff 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -432,6 +432,7 @@ enum data_queue_flags {
432 * @flags: Entry flags, see &enum queue_entry_flags. 432 * @flags: Entry flags, see &enum queue_entry_flags.
433 * @status_lock: The mutex for protecting the start/stop/flush 433 * @status_lock: The mutex for protecting the start/stop/flush
434 * handling on this queue. 434 * handling on this queue.
435 * @tx_lock: Spinlock to serialize tx operations on this queue.
435 * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or 436 * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
436 * @index_crypt needs to be changed this lock should be grabbed to prevent 437 * @index_crypt needs to be changed this lock should be grabbed to prevent
437 * index corruption due to concurrency. 438 * index corruption due to concurrency.
@@ -458,6 +459,7 @@ struct data_queue {
458 unsigned long flags; 459 unsigned long flags;
459 460
460 struct mutex status_lock; 461 struct mutex status_lock;
462 spinlock_t tx_lock;
461 spinlock_t index_lock; 463 spinlock_t index_lock;
462 464
463 unsigned int count; 465 unsigned int count;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 9d35ec16a3a5..53110b83bf6e 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2982,6 +2982,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
2982 .set_antenna = rt2x00mac_set_antenna, 2982 .set_antenna = rt2x00mac_set_antenna,
2983 .get_antenna = rt2x00mac_get_antenna, 2983 .get_antenna = rt2x00mac_get_antenna,
2984 .get_ringparam = rt2x00mac_get_ringparam, 2984 .get_ringparam = rt2x00mac_get_ringparam,
2985 .tx_frames_pending = rt2x00mac_tx_frames_pending,
2985}; 2986};
2986 2987
2987static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { 2988static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ad20953cbf05..6a93939f44e8 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2314,6 +2314,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
2314 .set_antenna = rt2x00mac_set_antenna, 2314 .set_antenna = rt2x00mac_set_antenna,
2315 .get_antenna = rt2x00mac_get_antenna, 2315 .get_antenna = rt2x00mac_get_antenna,
2316 .get_ringparam = rt2x00mac_get_ringparam, 2316 .get_ringparam = rt2x00mac_get_ringparam,
2317 .tx_frames_pending = rt2x00mac_tx_frames_pending,
2317}; 2318};
2318 2319
2319static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { 2320static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {