diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800.h | 27 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 130 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 119 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800usb.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 16 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00config.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00crypto.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 63 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00firmware.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00ht.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 135 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 4 |
17 files changed, 398 insertions, 236 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8ddaae44d7fb..baadf03a800e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -355,7 +355,9 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | |||
355 | * it is known that not work at least on some hardware. | 355 | * it is known that not work at least on some hardware. |
356 | * SW crypto will be used in that case. | 356 | * SW crypto will be used in that case. |
357 | */ | 357 | */ |
358 | if (key->alg == ALG_WEP && key->keyidx != 0) | 358 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
359 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
360 | key->keyidx != 0) | ||
359 | return -EOPNOTSUPP; | 361 | return -EOPNOTSUPP; |
360 | 362 | ||
361 | /* | 363 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ed4ebcdde7c9..cf1f16bfcd5e 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1318,7 +1318,25 @@ | |||
1318 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) | 1318 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) |
1319 | 1319 | ||
1320 | /* | 1320 | /* |
1321 | * TX_STA_FIFO: TX Result for specific PID status fifo register | 1321 | * TX_STA_FIFO: TX Result for specific PID status fifo register. |
1322 | * | ||
1323 | * This register is implemented as FIFO with 16 entries in the HW. Each | ||
1324 | * register read fetches the next tx result. If the FIFO is full because | ||
1325 | * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS) | ||
1326 | * triggered, the hw seems to simply drop further tx results. | ||
1327 | * | ||
1328 | * VALID: 1: this tx result is valid | ||
1329 | * 0: no valid tx result -> driver should stop reading | ||
1330 | * PID_TYPE: The PID latched from the PID field in the TXWI, can be used | ||
1331 | * to match a frame with its tx result (even though the PID is | ||
1332 | * only 4 bits wide). | ||
1333 | * TX_SUCCESS: Indicates tx success (1) or failure (0) | ||
1334 | * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0) | ||
1335 | * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0) | ||
1336 | * WCID: The wireless client ID. | ||
1337 | * MCS: The tx rate used during the last transmission of this frame, be it | ||
1338 | * successful or not. | ||
1339 | * PHYMODE: The phymode used for the transmission. | ||
1322 | */ | 1340 | */ |
1323 | #define TX_STA_FIFO 0x1718 | 1341 | #define TX_STA_FIFO 0x1718 |
1324 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) | 1342 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) |
@@ -1945,6 +1963,13 @@ struct mac_iveiv_entry { | |||
1945 | 1963 | ||
1946 | /* | 1964 | /* |
1947 | * Word1 | 1965 | * Word1 |
1966 | * ACK: 0: No Ack needed, 1: Ack needed | ||
1967 | * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number | ||
1968 | * BW_WIN_SIZE: BA windows size of the recipient | ||
1969 | * WIRELESS_CLI_ID: Client ID for WCID table access | ||
1970 | * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame | ||
1971 | * PACKETID: Will be latched into the TX_STA_FIFO register once the according | ||
1972 | * frame was processed. 0: Don't report tx status for this frame. | ||
1948 | */ | 1973 | */ |
1949 | #define TXWI_W1_ACK FIELD32(0x00000001) | 1974 | #define TXWI_W1_ACK FIELD32(0x00000001) |
1950 | #define TXWI_W1_NSEQ FIELD32(0x00000002) | 1975 | #define TXWI_W1_NSEQ FIELD32(0x00000002) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8c00fbda8664..6a0cb2d924d8 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
2 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | 3 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 4 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> |
4 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 5 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
@@ -427,8 +428,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
427 | } | 428 | } |
428 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); | 429 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); |
429 | 430 | ||
430 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | 431 | void rt2800_write_tx_data(struct queue_entry *entry, |
432 | struct txentry_desc *txdesc) | ||
431 | { | 433 | { |
434 | __le32 *txwi = rt2800_drv_get_txwi(entry); | ||
432 | u32 word; | 435 | u32 word; |
433 | 436 | ||
434 | /* | 437 | /* |
@@ -437,7 +440,8 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
437 | rt2x00_desc_read(txwi, 0, &word); | 440 | rt2x00_desc_read(txwi, 0, &word); |
438 | rt2x00_set_field32(&word, TXWI_W0_FRAG, | 441 | rt2x00_set_field32(&word, TXWI_W0_FRAG, |
439 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | 442 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); |
440 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); | 443 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, |
444 | test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags)); | ||
441 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); | 445 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); |
442 | rt2x00_set_field32(&word, TXWI_W0_TS, | 446 | rt2x00_set_field32(&word, TXWI_W0_TS, |
443 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); | 447 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); |
@@ -478,7 +482,7 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
478 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); | 482 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); |
479 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); | 483 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); |
480 | } | 484 | } |
481 | EXPORT_SYMBOL_GPL(rt2800_write_txwi); | 485 | EXPORT_SYMBOL_GPL(rt2800_write_tx_data); |
482 | 486 | ||
483 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) | 487 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) |
484 | { | 488 | { |
@@ -490,7 +494,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) | |||
490 | u8 offset1; | 494 | u8 offset1; |
491 | u8 offset2; | 495 | u8 offset2; |
492 | 496 | ||
493 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { | 497 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
494 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); | 498 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); |
495 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); | 499 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); |
496 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); | 500 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); |
@@ -569,6 +573,122 @@ void rt2800_process_rxwi(struct queue_entry *entry, | |||
569 | } | 573 | } |
570 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 574 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
571 | 575 | ||
576 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | ||
577 | { | ||
578 | struct data_queue *queue; | ||
579 | struct queue_entry *entry; | ||
580 | __le32 *txwi; | ||
581 | struct txdone_entry_desc txdesc; | ||
582 | u32 word; | ||
583 | u32 reg; | ||
584 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | ||
585 | u16 mcs, real_mcs; | ||
586 | int i; | ||
587 | |||
588 | /* | ||
589 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO | ||
590 | * at most X times and also stop processing once the TX_STA_FIFO_VALID | ||
591 | * flag is not set anymore. | ||
592 | * | ||
593 | * The legacy drivers use X=TX_RING_SIZE but state in a comment | ||
594 | * that the TX_STA_FIFO stack has a size of 16. We stick to our | ||
595 | * tx ring size for now. | ||
596 | */ | ||
597 | for (i = 0; i < TX_ENTRIES; i++) { | ||
598 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
599 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
600 | break; | ||
601 | |||
602 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
603 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
604 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
605 | |||
606 | /* | ||
607 | * Skip this entry when it contains an invalid | ||
608 | * queue identication number. | ||
609 | */ | ||
610 | if (pid <= 0 || pid > QID_RX) | ||
611 | continue; | ||
612 | |||
613 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); | ||
614 | if (unlikely(!queue)) | ||
615 | continue; | ||
616 | |||
617 | /* | ||
618 | * Inside each queue, we process each entry in a chronological | ||
619 | * order. We first check that the queue is not empty. | ||
620 | */ | ||
621 | entry = NULL; | ||
622 | while (!rt2x00queue_empty(queue)) { | ||
623 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
624 | if (!test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
625 | break; | ||
626 | |||
627 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
628 | } | ||
629 | |||
630 | if (!entry || rt2x00queue_empty(queue)) | ||
631 | break; | ||
632 | |||
633 | /* | ||
634 | * Check if we got a match by looking at WCID/ACK/PID | ||
635 | * fields | ||
636 | */ | ||
637 | txwi = rt2800_drv_get_txwi(entry); | ||
638 | |||
639 | rt2x00_desc_read(txwi, 1, &word); | ||
640 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
641 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
642 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
643 | |||
644 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) | ||
645 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content"); | ||
646 | |||
647 | /* | ||
648 | * Obtain the status about this packet. | ||
649 | */ | ||
650 | txdesc.flags = 0; | ||
651 | rt2x00_desc_read(txwi, 0, &word); | ||
652 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
653 | mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
654 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
655 | |||
656 | /* | ||
657 | * Ralink has a retry mechanism using a global fallback | ||
658 | * table. We setup this fallback table to try the immediate | ||
659 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
660 | * always contains the MCS used for the last transmission, be | ||
661 | * it successful or not. | ||
662 | */ | ||
663 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
664 | /* | ||
665 | * Transmission succeeded. The number of retries is | ||
666 | * mcs - real_mcs | ||
667 | */ | ||
668 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
669 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
670 | } else { | ||
671 | /* | ||
672 | * Transmission failed. The number of retries is | ||
673 | * always 7 in this case (for a total number of 8 | ||
674 | * frames sent). | ||
675 | */ | ||
676 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
677 | txdesc.retry = rt2x00dev->long_retry; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * the frame was retried at least once | ||
682 | * -> hw used fallback rates | ||
683 | */ | ||
684 | if (txdesc.retry) | ||
685 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
686 | |||
687 | rt2x00lib_txdone(entry, &txdesc); | ||
688 | } | ||
689 | } | ||
690 | EXPORT_SYMBOL_GPL(rt2800_txdone); | ||
691 | |||
572 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | 692 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) |
573 | { | 693 | { |
574 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 694 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
@@ -600,7 +720,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
600 | /* | 720 | /* |
601 | * Add the TXWI for the beacon to the skb. | 721 | * Add the TXWI for the beacon to the skb. |
602 | */ | 722 | */ |
603 | rt2800_write_txwi((__le32 *)entry->skb->data, txdesc); | 723 | rt2800_write_tx_data(entry, txdesc); |
604 | 724 | ||
605 | /* | 725 | /* |
606 | * Dump beacon to userspace through debugfs. | 726 | * Dump beacon to userspace through debugfs. |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 091641e3c5e2..3b572c63382d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
3 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
2 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz | 4 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz |
3 | 5 | ||
4 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
@@ -44,6 +46,7 @@ struct rt2800_ops { | |||
44 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, | 46 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, |
45 | const u8 *data, const size_t len); | 47 | const u8 *data, const size_t len); |
46 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); | 48 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); |
49 | __le32 *(*drv_get_txwi)(struct queue_entry *entry); | ||
47 | }; | 50 | }; |
48 | 51 | ||
49 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, | 52 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, |
@@ -126,6 +129,13 @@ static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) | |||
126 | return rt2800ops->drv_init_registers(rt2x00dev); | 129 | return rt2800ops->drv_init_registers(rt2x00dev); |
127 | } | 130 | } |
128 | 131 | ||
132 | static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry) | ||
133 | { | ||
134 | const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv; | ||
135 | |||
136 | return rt2800ops->drv_get_txwi(entry); | ||
137 | } | ||
138 | |||
129 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | 139 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, |
130 | const u8 command, const u8 token, | 140 | const u8 command, const u8 token, |
131 | const u8 arg0, const u8 arg1); | 141 | const u8 arg0, const u8 arg1); |
@@ -135,9 +145,12 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | |||
135 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | 145 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, |
136 | const u8 *data, const size_t len); | 146 | const u8 *data, const size_t len); |
137 | 147 | ||
138 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); | 148 | void rt2800_write_tx_data(struct queue_entry *entry, |
149 | struct txentry_desc *txdesc); | ||
139 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); | 150 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); |
140 | 151 | ||
152 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev); | ||
153 | |||
141 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 154 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
142 | 155 | ||
143 | extern const struct rt2x00debug rt2800_rt2x00debug; | 156 | extern const struct rt2x00debug rt2800_rt2x00debug; |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 39b3846fa340..4390f2b74b2e 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | 3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | 5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> |
@@ -566,15 +566,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
566 | /* | 566 | /* |
567 | * TX descriptor initialization | 567 | * TX descriptor initialization |
568 | */ | 568 | */ |
569 | static void rt2800pci_write_tx_data(struct queue_entry* entry, | 569 | static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) |
570 | struct txentry_desc *txdesc) | ||
571 | { | 570 | { |
572 | __le32 *txwi = (__le32 *) entry->skb->data; | 571 | return (__le32 *) entry->skb->data; |
573 | |||
574 | rt2800_write_txwi(txwi, txdesc); | ||
575 | } | 572 | } |
576 | 573 | ||
577 | |||
578 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 574 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
579 | struct sk_buff *skb, | 575 | struct sk_buff *skb, |
580 | struct txentry_desc *txdesc) | 576 | struct txentry_desc *txdesc) |
@@ -728,110 +724,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
728 | /* | 724 | /* |
729 | * Interrupt functions. | 725 | * Interrupt functions. |
730 | */ | 726 | */ |
731 | static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
732 | { | ||
733 | struct data_queue *queue; | ||
734 | struct queue_entry *entry; | ||
735 | __le32 *txwi; | ||
736 | struct txdone_entry_desc txdesc; | ||
737 | u32 word; | ||
738 | u32 reg; | ||
739 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | ||
740 | u16 mcs, real_mcs; | ||
741 | int i; | ||
742 | |||
743 | /* | ||
744 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO | ||
745 | * at most X times and also stop processing once the TX_STA_FIFO_VALID | ||
746 | * flag is not set anymore. | ||
747 | * | ||
748 | * The legacy drivers use X=TX_RING_SIZE but state in a comment | ||
749 | * that the TX_STA_FIFO stack has a size of 16. We stick to our | ||
750 | * tx ring size for now. | ||
751 | */ | ||
752 | for (i = 0; i < TX_ENTRIES; i++) { | ||
753 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
754 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
755 | break; | ||
756 | |||
757 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
758 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
759 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
760 | |||
761 | /* | ||
762 | * Skip this entry when it contains an invalid | ||
763 | * queue identication number. | ||
764 | */ | ||
765 | if (pid <= 0 || pid > QID_RX) | ||
766 | continue; | ||
767 | |||
768 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); | ||
769 | if (unlikely(!queue)) | ||
770 | continue; | ||
771 | |||
772 | /* | ||
773 | * Inside each queue, we process each entry in a chronological | ||
774 | * order. We first check that the queue is not empty. | ||
775 | */ | ||
776 | if (rt2x00queue_empty(queue)) | ||
777 | continue; | ||
778 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
779 | |||
780 | /* Check if we got a match by looking at WCID/ACK/PID | ||
781 | * fields */ | ||
782 | txwi = (__le32 *) entry->skb->data; | ||
783 | |||
784 | rt2x00_desc_read(txwi, 1, &word); | ||
785 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
786 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
787 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
788 | |||
789 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) | ||
790 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n"); | ||
791 | |||
792 | /* | ||
793 | * Obtain the status about this packet. | ||
794 | */ | ||
795 | txdesc.flags = 0; | ||
796 | rt2x00_desc_read(txwi, 0, &word); | ||
797 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
798 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
799 | |||
800 | /* | ||
801 | * Ralink has a retry mechanism using a global fallback | ||
802 | * table. We setup this fallback table to try the immediate | ||
803 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
804 | * always contains the MCS used for the last transmission, be | ||
805 | * it successful or not. | ||
806 | */ | ||
807 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
808 | /* | ||
809 | * Transmission succeeded. The number of retries is | ||
810 | * mcs - real_mcs | ||
811 | */ | ||
812 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
813 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
814 | } else { | ||
815 | /* | ||
816 | * Transmission failed. The number of retries is | ||
817 | * always 7 in this case (for a total number of 8 | ||
818 | * frames sent). | ||
819 | */ | ||
820 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
821 | txdesc.retry = 7; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * the frame was retried at least once | ||
826 | * -> hw used fallback rates | ||
827 | */ | ||
828 | if (txdesc.retry) | ||
829 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
830 | |||
831 | rt2x00lib_txdone(entry, &txdesc); | ||
832 | } | ||
833 | } | ||
834 | |||
835 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | 727 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) |
836 | { | 728 | { |
837 | struct ieee80211_conf conf = { .flags = 0 }; | 729 | struct ieee80211_conf conf = { .flags = 0 }; |
@@ -867,7 +759,7 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | |||
867 | * 4 - Tx done interrupt. | 759 | * 4 - Tx done interrupt. |
868 | */ | 760 | */ |
869 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 761 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
870 | rt2800pci_txdone(rt2x00dev); | 762 | rt2800_txdone(rt2x00dev); |
871 | 763 | ||
872 | /* | 764 | /* |
873 | * 5 - Auto wakeup interrupt. | 765 | * 5 - Auto wakeup interrupt. |
@@ -1011,6 +903,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
1011 | .regbusy_read = rt2x00pci_regbusy_read, | 903 | .regbusy_read = rt2x00pci_regbusy_read, |
1012 | .drv_write_firmware = rt2800pci_write_firmware, | 904 | .drv_write_firmware = rt2800pci_write_firmware, |
1013 | .drv_init_registers = rt2800pci_init_registers, | 905 | .drv_init_registers = rt2800pci_init_registers, |
906 | .drv_get_txwi = rt2800pci_get_txwi, | ||
1014 | }; | 907 | }; |
1015 | 908 | ||
1016 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 909 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
@@ -1030,7 +923,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1030 | .reset_tuner = rt2800_reset_tuner, | 923 | .reset_tuner = rt2800_reset_tuner, |
1031 | .link_tuner = rt2800_link_tuner, | 924 | .link_tuner = rt2800_link_tuner, |
1032 | .write_tx_desc = rt2800pci_write_tx_desc, | 925 | .write_tx_desc = rt2800pci_write_tx_desc, |
1033 | .write_tx_data = rt2800pci_write_tx_data, | 926 | .write_tx_data = rt2800_write_tx_data, |
1034 | .write_beacon = rt2800_write_beacon, | 927 | .write_beacon = rt2800_write_beacon, |
1035 | .kick_tx_queue = rt2800pci_kick_tx_queue, | 928 | .kick_tx_queue = rt2800pci_kick_tx_queue, |
1036 | .kill_tx_queue = rt2800pci_kill_tx_queue, | 929 | .kill_tx_queue = rt2800pci_kill_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5a2dfe87c6b6..9ad28be294eb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | 4 | Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 5 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | 6 | Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> |
@@ -320,15 +321,14 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
320 | /* | 321 | /* |
321 | * TX descriptor initialization | 322 | * TX descriptor initialization |
322 | */ | 323 | */ |
323 | static void rt2800usb_write_tx_data(struct queue_entry* entry, | 324 | static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) |
324 | struct txentry_desc *txdesc) | ||
325 | { | 325 | { |
326 | __le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); | 326 | if (entry->queue->qid == QID_BEACON) |
327 | 327 | return (__le32 *) (entry->skb->data); | |
328 | rt2800_write_txwi(txwi, txdesc); | 328 | else |
329 | return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); | ||
329 | } | 330 | } |
330 | 331 | ||
331 | |||
332 | static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 332 | static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
333 | struct sk_buff *skb, | 333 | struct sk_buff *skb, |
334 | struct txentry_desc *txdesc) | 334 | struct txentry_desc *txdesc) |
@@ -379,6 +379,38 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) | |||
379 | } | 379 | } |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * TX control handlers | ||
383 | */ | ||
384 | static void rt2800usb_work_txdone(struct work_struct *work) | ||
385 | { | ||
386 | struct rt2x00_dev *rt2x00dev = | ||
387 | container_of(work, struct rt2x00_dev, txdone_work); | ||
388 | struct data_queue *queue; | ||
389 | struct queue_entry *entry; | ||
390 | |||
391 | rt2800_txdone(rt2x00dev); | ||
392 | |||
393 | /* | ||
394 | * Process any trailing TX status reports for IO failures, | ||
395 | * we loop until we find the first non-IO error entry. This | ||
396 | * can either be a frame which is free, is being uploaded, | ||
397 | * or has completed the upload but didn't have an entry | ||
398 | * in the TX_STAT_FIFO register yet. | ||
399 | */ | ||
400 | tx_queue_for_each(rt2x00dev, queue) { | ||
401 | while (!rt2x00queue_empty(queue)) { | ||
402 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
403 | |||
404 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || | ||
405 | !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
406 | break; | ||
407 | |||
408 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /* | ||
382 | * RX control handlers | 414 | * RX control handlers |
383 | */ | 415 | */ |
384 | static void rt2800usb_fill_rxdone(struct queue_entry *entry, | 416 | static void rt2800usb_fill_rxdone(struct queue_entry *entry, |
@@ -514,6 +546,11 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
514 | */ | 546 | */ |
515 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; | 547 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; |
516 | 548 | ||
549 | /* | ||
550 | * Overwrite TX done handler | ||
551 | */ | ||
552 | PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone); | ||
553 | |||
517 | return 0; | 554 | return 0; |
518 | } | 555 | } |
519 | 556 | ||
@@ -549,6 +586,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { | |||
549 | .regbusy_read = rt2x00usb_regbusy_read, | 586 | .regbusy_read = rt2x00usb_regbusy_read, |
550 | .drv_write_firmware = rt2800usb_write_firmware, | 587 | .drv_write_firmware = rt2800usb_write_firmware, |
551 | .drv_init_registers = rt2800usb_init_registers, | 588 | .drv_init_registers = rt2800usb_init_registers, |
589 | .drv_get_txwi = rt2800usb_get_txwi, | ||
552 | }; | 590 | }; |
553 | 591 | ||
554 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | 592 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { |
@@ -566,7 +604,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
566 | .link_tuner = rt2800_link_tuner, | 604 | .link_tuner = rt2800_link_tuner, |
567 | .watchdog = rt2x00usb_watchdog, | 605 | .watchdog = rt2x00usb_watchdog, |
568 | .write_tx_desc = rt2800usb_write_tx_desc, | 606 | .write_tx_desc = rt2800usb_write_tx_desc, |
569 | .write_tx_data = rt2800usb_write_tx_data, | 607 | .write_tx_data = rt2800_write_tx_data, |
570 | .write_beacon = rt2800_write_beacon, | 608 | .write_beacon = rt2800_write_beacon, |
571 | .get_tx_data_len = rt2800usb_get_tx_data_len, | 609 | .get_tx_data_len = rt2800usb_get_tx_data_len, |
572 | .kick_tx_queue = rt2x00usb_kick_tx_queue, | 610 | .kick_tx_queue = rt2x00usb_kick_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c21af38cc5af..8c65244a847a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | <http://rt2x00.serialmonkey.com> | 5 | <http://rt2x00.serialmonkey.com> |
5 | 6 | ||
@@ -698,6 +699,7 @@ struct rt2x00_dev { | |||
698 | struct ieee80211_hw *hw; | 699 | struct ieee80211_hw *hw; |
699 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 700 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
700 | enum ieee80211_band curr_band; | 701 | enum ieee80211_band curr_band; |
702 | int curr_freq; | ||
701 | 703 | ||
702 | /* | 704 | /* |
703 | * If enabled, the debugfs interface structures | 705 | * If enabled, the debugfs interface structures |
@@ -850,11 +852,6 @@ struct rt2x00_dev { | |||
850 | struct ieee80211_low_level_stats low_level_stats; | 852 | struct ieee80211_low_level_stats low_level_stats; |
851 | 853 | ||
852 | /* | 854 | /* |
853 | * RX configuration information. | ||
854 | */ | ||
855 | struct ieee80211_rx_status rx_status; | ||
856 | |||
857 | /* | ||
858 | * Scheduled work. | 855 | * Scheduled work. |
859 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | 856 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() |
860 | * which means it cannot be placed on the hw->workqueue | 857 | * which means it cannot be placed on the hw->workqueue |
@@ -862,6 +859,12 @@ struct rt2x00_dev { | |||
862 | */ | 859 | */ |
863 | struct work_struct intf_work; | 860 | struct work_struct intf_work; |
864 | 861 | ||
862 | /** | ||
863 | * Scheduled work for TX/RX done handling (USB devices) | ||
864 | */ | ||
865 | struct work_struct rxdone_work; | ||
866 | struct work_struct txdone_work; | ||
867 | |||
865 | /* | 868 | /* |
866 | * Data queue arrays for RX, TX and Beacon. | 869 | * Data queue arrays for RX, TX and Beacon. |
867 | * The Beacon array also contains the Atim queue | 870 | * The Beacon array also contains the Atim queue |
@@ -1071,6 +1074,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | |||
1071 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); | 1074 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); |
1072 | void rt2x00lib_txdone(struct queue_entry *entry, | 1075 | void rt2x00lib_txdone(struct queue_entry *entry, |
1073 | struct txdone_entry_desc *txdesc); | 1076 | struct txdone_entry_desc *txdesc); |
1077 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); | ||
1074 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | 1078 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
1075 | struct queue_entry *entry); | 1079 | struct queue_entry *entry); |
1076 | 1080 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 953dc4f2c6af..34f34fa7f53a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -126,11 +126,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
126 | * ANTENNA_SW_DIVERSITY state to the driver. | 126 | * ANTENNA_SW_DIVERSITY state to the driver. |
127 | * If that happens, fallback to hardware defaults, | 127 | * If that happens, fallback to hardware defaults, |
128 | * or our own default. | 128 | * or our own default. |
129 | * If diversity handling is active for a particular antenna, | ||
130 | * we shouldn't overwrite that antenna. | ||
131 | * The calls to rt2x00lib_config_antenna_check() | ||
132 | * might have caused that we restore back to the already | ||
133 | * active setting. If that has happened we can quit. | ||
134 | */ | 129 | */ |
135 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) | 130 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) |
136 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); | 131 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); |
@@ -142,9 +137,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
142 | else | 137 | else |
143 | config.tx = active->tx; | 138 | config.tx = active->tx; |
144 | 139 | ||
145 | if (config.rx == active->rx && config.tx == active->tx) | ||
146 | return; | ||
147 | |||
148 | /* | 140 | /* |
149 | * Antenna setup changes require the RX to be disabled, | 141 | * Antenna setup changes require the RX to be disabled, |
150 | * else the changes will be ignored by the device. | 142 | * else the changes will be ignored by the device. |
@@ -209,10 +201,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
209 | rt2x00link_reset_tuner(rt2x00dev, false); | 201 | rt2x00link_reset_tuner(rt2x00dev, false); |
210 | 202 | ||
211 | rt2x00dev->curr_band = conf->channel->band; | 203 | rt2x00dev->curr_band = conf->channel->band; |
204 | rt2x00dev->curr_freq = conf->channel->center_freq; | ||
212 | rt2x00dev->tx_power = conf->power_level; | 205 | rt2x00dev->tx_power = conf->power_level; |
213 | rt2x00dev->short_retry = conf->short_frame_max_tx_count; | 206 | rt2x00dev->short_retry = conf->short_frame_max_tx_count; |
214 | rt2x00dev->long_retry = conf->long_frame_max_tx_count; | 207 | rt2x00dev->long_retry = conf->long_frame_max_tx_count; |
215 | |||
216 | rt2x00dev->rx_status.band = conf->channel->band; | ||
217 | rt2x00dev->rx_status.freq = conf->channel->center_freq; | ||
218 | } | 208 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 583dacd8d241..5e9074bf2b8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -31,15 +31,14 @@ | |||
31 | 31 | ||
32 | enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) | 32 | enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) |
33 | { | 33 | { |
34 | switch (key->alg) { | 34 | switch (key->cipher) { |
35 | case ALG_WEP: | 35 | case WLAN_CIPHER_SUITE_WEP40: |
36 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 36 | return CIPHER_WEP64; |
37 | return CIPHER_WEP64; | 37 | case WLAN_CIPHER_SUITE_WEP104: |
38 | else | 38 | return CIPHER_WEP128; |
39 | return CIPHER_WEP128; | 39 | case WLAN_CIPHER_SUITE_TKIP: |
40 | case ALG_TKIP: | ||
41 | return CIPHER_TKIP; | 40 | return CIPHER_TKIP; |
42 | case ALG_CCMP: | 41 | case WLAN_CIPHER_SUITE_CCMP: |
43 | return CIPHER_AES; | 42 | return CIPHER_AES; |
44 | default: | 43 | default: |
45 | return CIPHER_NONE; | 44 | return CIPHER_NONE; |
@@ -95,7 +94,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, | |||
95 | overhead += key->iv_len; | 94 | overhead += key->iv_len; |
96 | 95 | ||
97 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 96 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
98 | if (key->alg == ALG_TKIP) | 97 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
99 | overhead += 8; | 98 | overhead += 8; |
100 | } | 99 | } |
101 | 100 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 585e8166f22a..e692608bee8b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | 4 | <http://rt2x00.serialmonkey.com> |
4 | 5 | ||
5 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
@@ -383,15 +384,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
383 | * send the status report back. | 384 | * send the status report back. |
384 | */ | 385 | */ |
385 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) | 386 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) |
386 | /* | 387 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); |
387 | * Only PCI and SOC devices process the tx status in process | ||
388 | * context. Hence use ieee80211_tx_status for PCI and SOC | ||
389 | * devices and stick to ieee80211_tx_status_irqsafe for USB. | ||
390 | */ | ||
391 | if (rt2x00_is_usb(rt2x00dev)) | ||
392 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | ||
393 | else | ||
394 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); | ||
395 | else | 388 | else |
396 | dev_kfree_skb_any(entry->skb); | 389 | dev_kfree_skb_any(entry->skb); |
397 | 390 | ||
@@ -403,7 +396,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
403 | 396 | ||
404 | rt2x00dev->ops->lib->clear_entry(entry); | 397 | rt2x00dev->ops->lib->clear_entry(entry); |
405 | 398 | ||
406 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
407 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 399 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
408 | 400 | ||
409 | /* | 401 | /* |
@@ -416,6 +408,18 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
416 | } | 408 | } |
417 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 409 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
418 | 410 | ||
411 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status) | ||
412 | { | ||
413 | struct txdone_entry_desc txdesc; | ||
414 | |||
415 | txdesc.flags = 0; | ||
416 | __set_bit(status, &txdesc.flags); | ||
417 | txdesc.retry = 0; | ||
418 | |||
419 | rt2x00lib_txdone(entry, &txdesc); | ||
420 | } | ||
421 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); | ||
422 | |||
419 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, | 423 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, |
420 | struct rxdone_entry_desc *rxdesc) | 424 | struct rxdone_entry_desc *rxdesc) |
421 | { | 425 | { |
@@ -460,9 +464,13 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
460 | { | 464 | { |
461 | struct rxdone_entry_desc rxdesc; | 465 | struct rxdone_entry_desc rxdesc; |
462 | struct sk_buff *skb; | 466 | struct sk_buff *skb; |
463 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 467 | struct ieee80211_rx_status *rx_status; |
464 | unsigned int header_length; | 468 | unsigned int header_length; |
465 | int rate_idx; | 469 | int rate_idx; |
470 | |||
471 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
472 | goto submit_entry; | ||
473 | |||
466 | /* | 474 | /* |
467 | * Allocate a new sk_buffer. If no new buffer available, drop the | 475 | * Allocate a new sk_buffer. If no new buffer available, drop the |
468 | * received frame and reuse the existing buffer. | 476 | * received frame and reuse the existing buffer. |
@@ -527,39 +535,32 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
527 | */ | 535 | */ |
528 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); | 536 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); |
529 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); | 537 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); |
538 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | ||
530 | 539 | ||
540 | /* | ||
541 | * Initialize RX status information, and send frame | ||
542 | * to mac80211. | ||
543 | */ | ||
544 | rx_status = IEEE80211_SKB_RXCB(entry->skb); | ||
531 | rx_status->mactime = rxdesc.timestamp; | 545 | rx_status->mactime = rxdesc.timestamp; |
546 | rx_status->band = rt2x00dev->curr_band; | ||
547 | rx_status->freq = rt2x00dev->curr_freq; | ||
532 | rx_status->rate_idx = rate_idx; | 548 | rx_status->rate_idx = rate_idx; |
533 | rx_status->signal = rxdesc.rssi; | 549 | rx_status->signal = rxdesc.rssi; |
534 | rx_status->flag = rxdesc.flags; | 550 | rx_status->flag = rxdesc.flags; |
535 | rx_status->antenna = rt2x00dev->link.ant.active.rx; | 551 | rx_status->antenna = rt2x00dev->link.ant.active.rx; |
536 | 552 | ||
537 | /* | 553 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); |
538 | * Send frame to mac80211 & debugfs. | ||
539 | * mac80211 will clean up the skb structure. | ||
540 | */ | ||
541 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | ||
542 | memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); | ||
543 | |||
544 | /* | ||
545 | * Currently only PCI and SOC devices handle rx interrupts in process | ||
546 | * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni | ||
547 | * for PCI and SOC devices. | ||
548 | */ | ||
549 | if (rt2x00_is_usb(rt2x00dev)) | ||
550 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); | ||
551 | else | ||
552 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); | ||
553 | 554 | ||
554 | /* | 555 | /* |
555 | * Replace the skb with the freshly allocated one. | 556 | * Replace the skb with the freshly allocated one. |
556 | */ | 557 | */ |
557 | entry->skb = skb; | 558 | entry->skb = skb; |
558 | entry->flags = 0; | ||
559 | 559 | ||
560 | submit_entry: | ||
560 | rt2x00dev->ops->lib->clear_entry(entry); | 561 | rt2x00dev->ops->lib->clear_entry(entry); |
561 | |||
562 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | 562 | rt2x00queue_index_inc(entry->queue, Q_INDEX); |
563 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
563 | } | 564 | } |
564 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | 565 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); |
565 | 566 | ||
@@ -1017,6 +1018,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1017 | * Stop all work. | 1018 | * Stop all work. |
1018 | */ | 1019 | */ |
1019 | cancel_work_sync(&rt2x00dev->intf_work); | 1020 | cancel_work_sync(&rt2x00dev->intf_work); |
1021 | cancel_work_sync(&rt2x00dev->rxdone_work); | ||
1022 | cancel_work_sync(&rt2x00dev->txdone_work); | ||
1020 | 1023 | ||
1021 | /* | 1024 | /* |
1022 | * Uninitialize device. | 1025 | * Uninitialize device. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b818a43c4672..f0e1eb72befc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c | |||
@@ -63,6 +63,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) | |||
63 | 63 | ||
64 | INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", | 64 | INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", |
65 | fw->data[fw->size - 4], fw->data[fw->size - 3]); | 65 | fw->data[fw->size - 4], fw->data[fw->size - 3]); |
66 | snprintf(rt2x00dev->hw->wiphy->fw_version, | ||
67 | sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d", | ||
68 | fw->data[fw->size - 4], fw->data[fw->size - 3]); | ||
66 | 69 | ||
67 | retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); | 70 | retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); |
68 | switch (retval) { | 71 | switch (retval) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index c004cd3a8847..ad3c7ff4837b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c | |||
@@ -54,6 +54,16 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
54 | */ | 54 | */ |
55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | 55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { |
56 | txdesc->mcs = txrate->idx; | 56 | txdesc->mcs = txrate->idx; |
57 | |||
58 | /* | ||
59 | * MIMO PS should be set to 1 for STA's using dynamic SM PS | ||
60 | * when using more then one tx stream (>MCS7). | ||
61 | */ | ||
62 | if (tx_info->control.sta && txdesc->mcs > 7 && | ||
63 | (tx_info->control.sta->ht_cap.cap & | ||
64 | (WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
65 | IEEE80211_HT_CAP_SM_PS_SHIFT))) | ||
66 | __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); | ||
57 | } else { | 67 | } else { |
58 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | 68 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); |
59 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 69 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9c609be95083..480d33a3ce42 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | <http://rt2x00.serialmonkey.com> | 5 | <http://rt2x00.serialmonkey.com> |
5 | 6 | ||
@@ -730,9 +731,9 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) | |||
730 | rt2x00queue_reset(queue); | 731 | rt2x00queue_reset(queue); |
731 | 732 | ||
732 | for (i = 0; i < queue->limit; i++) { | 733 | for (i = 0; i < queue->limit; i++) { |
733 | queue->entries[i].flags = 0; | ||
734 | |||
735 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); | 734 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); |
735 | if (queue->qid == QID_RX) | ||
736 | rt2x00queue_index_inc(queue, Q_INDEX); | ||
736 | } | 737 | } |
737 | } | 738 | } |
738 | } | 739 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 191e7775a9c0..2d3bf843735f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | <http://rt2x00.serialmonkey.com> | 3 | <http://rt2x00.serialmonkey.com> |
4 | 4 | ||
5 | This program is free software; you can redistribute it and/or modify | 5 | This program is free software; you can redistribute it and/or modify |
@@ -268,6 +268,7 @@ struct txdone_entry_desc { | |||
268 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. | 268 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. |
269 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. | 269 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. |
270 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. | 270 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. |
271 | * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode. | ||
271 | */ | 272 | */ |
272 | enum txentry_desc_flags { | 273 | enum txentry_desc_flags { |
273 | ENTRY_TXD_RTS_FRAME, | 274 | ENTRY_TXD_RTS_FRAME, |
@@ -286,6 +287,7 @@ enum txentry_desc_flags { | |||
286 | ENTRY_TXD_HT_AMPDU, | 287 | ENTRY_TXD_HT_AMPDU, |
287 | ENTRY_TXD_HT_BW_40, | 288 | ENTRY_TXD_HT_BW_40, |
288 | ENTRY_TXD_HT_SHORT_GI, | 289 | ENTRY_TXD_HT_SHORT_GI, |
290 | ENTRY_TXD_HT_MIMO_PS, | ||
289 | }; | 291 | }; |
290 | 292 | ||
291 | /** | 293 | /** |
@@ -363,12 +365,16 @@ struct txentry_desc { | |||
363 | * the device has signaled it is done with it. | 365 | * the device has signaled it is done with it. |
364 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting | 366 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting |
365 | * for the signal to start sending. | 367 | * for the signal to start sending. |
368 | * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured | ||
369 | * while transfering the data to the hardware. No TX status report will | ||
370 | * be expected from the hardware. | ||
366 | */ | 371 | */ |
367 | enum queue_entry_flags { | 372 | enum queue_entry_flags { |
368 | ENTRY_BCN_ASSIGNED, | 373 | ENTRY_BCN_ASSIGNED, |
369 | ENTRY_OWNER_DEVICE_DATA, | 374 | ENTRY_OWNER_DEVICE_DATA, |
370 | ENTRY_OWNER_DEVICE_CRYPTO, | 375 | ENTRY_OWNER_DEVICE_CRYPTO, |
371 | ENTRY_DATA_PENDING, | 376 | ENTRY_DATA_PENDING, |
377 | ENTRY_DATA_IO_FAILED | ||
372 | }; | 378 | }; |
373 | 379 | ||
374 | /** | 380 | /** |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index ff3a36622d1b..f76014f732ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | 4 | <http://rt2x00.serialmonkey.com> |
4 | 5 | ||
5 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
@@ -167,33 +168,61 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); | |||
167 | /* | 168 | /* |
168 | * TX data handlers. | 169 | * TX data handlers. |
169 | */ | 170 | */ |
171 | static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) | ||
172 | { | ||
173 | /* | ||
174 | * If the transfer to hardware succeeded, it does not mean the | ||
175 | * frame was send out correctly. It only means the frame | ||
176 | * was succesfully pushed to the hardware, we have no | ||
177 | * way to determine the transmission status right now. | ||
178 | * (Only indirectly by looking at the failed TX counters | ||
179 | * in the register). | ||
180 | */ | ||
181 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
182 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
183 | else | ||
184 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); | ||
185 | } | ||
186 | |||
187 | static void rt2x00usb_work_txdone(struct work_struct *work) | ||
188 | { | ||
189 | struct rt2x00_dev *rt2x00dev = | ||
190 | container_of(work, struct rt2x00_dev, txdone_work); | ||
191 | struct data_queue *queue; | ||
192 | struct queue_entry *entry; | ||
193 | |||
194 | tx_queue_for_each(rt2x00dev, queue) { | ||
195 | while (!rt2x00queue_empty(queue)) { | ||
196 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
197 | |||
198 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
199 | break; | ||
200 | |||
201 | rt2x00usb_work_txdone_entry(entry); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
170 | static void rt2x00usb_interrupt_txdone(struct urb *urb) | 206 | static void rt2x00usb_interrupt_txdone(struct urb *urb) |
171 | { | 207 | { |
172 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 208 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
173 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 209 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
174 | struct txdone_entry_desc txdesc; | ||
175 | 210 | ||
176 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 211 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
177 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 212 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
178 | return; | 213 | return; |
179 | 214 | ||
180 | /* | 215 | /* |
181 | * Obtain the status about this packet. | 216 | * Check if the frame was correctly uploaded |
182 | * Note that when the status is 0 it does not mean the | ||
183 | * frame was send out correctly. It only means the frame | ||
184 | * was succesfully pushed to the hardware, we have no | ||
185 | * way to determine the transmission status right now. | ||
186 | * (Only indirectly by looking at the failed TX counters | ||
187 | * in the register). | ||
188 | */ | 217 | */ |
189 | txdesc.flags = 0; | 218 | if (urb->status) |
190 | if (!urb->status) | 219 | __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
191 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
192 | else | ||
193 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
194 | txdesc.retry = 0; | ||
195 | 220 | ||
196 | rt2x00lib_txdone(entry, &txdesc); | 221 | /* |
222 | * Schedule the delayed work for reading the TX status | ||
223 | * from the device. | ||
224 | */ | ||
225 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); | ||
197 | } | 226 | } |
198 | 227 | ||
199 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 228 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) |
@@ -294,6 +323,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); | |||
294 | 323 | ||
295 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | 324 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) |
296 | { | 325 | { |
326 | struct queue_entry *entry; | ||
297 | struct queue_entry_priv_usb *entry_priv; | 327 | struct queue_entry_priv_usb *entry_priv; |
298 | unsigned short threshold = queue->threshold; | 328 | unsigned short threshold = queue->threshold; |
299 | 329 | ||
@@ -313,14 +343,22 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | |||
313 | * Reset all currently uploaded TX frames. | 343 | * Reset all currently uploaded TX frames. |
314 | */ | 344 | */ |
315 | while (!rt2x00queue_empty(queue)) { | 345 | while (!rt2x00queue_empty(queue)) { |
316 | entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data; | 346 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
347 | entry_priv = entry->priv_data; | ||
317 | usb_kill_urb(entry_priv->urb); | 348 | usb_kill_urb(entry_priv->urb); |
318 | 349 | ||
319 | /* | 350 | /* |
320 | * We need a short delay here to wait for | 351 | * We need a short delay here to wait for |
321 | * the URB to be canceled and invoked the tx_done handler. | 352 | * the URB to be canceled |
353 | */ | ||
354 | do { | ||
355 | udelay(100); | ||
356 | } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); | ||
357 | |||
358 | /* | ||
359 | * Invoke the TX done handler | ||
322 | */ | 360 | */ |
323 | udelay(200); | 361 | rt2x00usb_work_txdone_entry(entry); |
324 | } | 362 | } |
325 | 363 | ||
326 | /* | 364 | /* |
@@ -345,15 +383,41 @@ EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | |||
345 | /* | 383 | /* |
346 | * RX data handlers. | 384 | * RX data handlers. |
347 | */ | 385 | */ |
386 | static void rt2x00usb_work_rxdone(struct work_struct *work) | ||
387 | { | ||
388 | struct rt2x00_dev *rt2x00dev = | ||
389 | container_of(work, struct rt2x00_dev, rxdone_work); | ||
390 | struct queue_entry *entry; | ||
391 | struct skb_frame_desc *skbdesc; | ||
392 | u8 rxd[32]; | ||
393 | |||
394 | while (!rt2x00queue_empty(rt2x00dev->rx)) { | ||
395 | entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); | ||
396 | |||
397 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
398 | break; | ||
399 | |||
400 | /* | ||
401 | * Fill in desc fields of the skb descriptor | ||
402 | */ | ||
403 | skbdesc = get_skb_frame_desc(entry->skb); | ||
404 | skbdesc->desc = rxd; | ||
405 | skbdesc->desc_len = entry->queue->desc_size; | ||
406 | |||
407 | /* | ||
408 | * Send the frame to rt2x00lib for further processing. | ||
409 | */ | ||
410 | rt2x00lib_rxdone(rt2x00dev, entry); | ||
411 | } | ||
412 | } | ||
413 | |||
348 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) | 414 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) |
349 | { | 415 | { |
350 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 416 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
351 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 417 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
352 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
353 | u8 rxd[32]; | ||
354 | 418 | ||
355 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 419 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
356 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 420 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
357 | return; | 421 | return; |
358 | 422 | ||
359 | /* | 423 | /* |
@@ -361,22 +425,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
361 | * to be actually valid, or if the urb is signaling | 425 | * to be actually valid, or if the urb is signaling |
362 | * a problem. | 426 | * a problem. |
363 | */ | 427 | */ |
364 | if (urb->actual_length < entry->queue->desc_size || urb->status) { | 428 | if (urb->actual_length < entry->queue->desc_size || urb->status) |
365 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 429 | __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
366 | usb_submit_urb(urb, GFP_ATOMIC); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Fill in desc fields of the skb descriptor | ||
372 | */ | ||
373 | skbdesc->desc = rxd; | ||
374 | skbdesc->desc_len = entry->queue->desc_size; | ||
375 | 430 | ||
376 | /* | 431 | /* |
377 | * Send the frame to rt2x00lib for further processing. | 432 | * Schedule the delayed work for reading the RX status |
433 | * from the device. | ||
378 | */ | 434 | */ |
379 | rt2x00lib_rxdone(rt2x00dev, entry); | 435 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); |
380 | } | 436 | } |
381 | 437 | ||
382 | /* | 438 | /* |
@@ -405,6 +461,8 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
405 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 461 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
406 | int pipe; | 462 | int pipe; |
407 | 463 | ||
464 | entry->flags = 0; | ||
465 | |||
408 | if (entry->queue->qid == QID_RX) { | 466 | if (entry->queue->qid == QID_RX) { |
409 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); | 467 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); |
410 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, | 468 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, |
@@ -413,8 +471,6 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
413 | 471 | ||
414 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 472 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
415 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | 473 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
416 | } else { | ||
417 | entry->flags = 0; | ||
418 | } | 474 | } |
419 | } | 475 | } |
420 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 476 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
@@ -659,6 +715,9 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
659 | 715 | ||
660 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); | 716 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
661 | 717 | ||
718 | INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); | ||
719 | INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); | ||
720 | |||
662 | retval = rt2x00usb_alloc_reg(rt2x00dev); | 721 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
663 | if (retval) | 722 | if (retval) |
664 | goto exit_free_device; | 723 | goto exit_free_device; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f226582dbc87..3f8d10b76fee 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1050,7 +1050,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
1050 | /* | 1050 | /* |
1051 | * Determine r17 bounds. | 1051 | * Determine r17 bounds. |
1052 | */ | 1052 | */ |
1053 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1053 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1054 | low_bound = 0x28; | 1054 | low_bound = 0x28; |
1055 | up_bound = 0x48; | 1055 | up_bound = 0x48; |
1056 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { | 1056 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { |
@@ -1972,7 +1972,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1972 | return 0; | 1972 | return 0; |
1973 | } | 1973 | } |
1974 | 1974 | ||
1975 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1975 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1976 | if (lna == 3 || lna == 2) | 1976 | if (lna == 3 || lna == 2) |
1977 | offset += 10; | 1977 | offset += 10; |
1978 | } | 1978 | } |
@@ -2107,11 +2107,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2107 | "TX status report missed for entry %d\n", | 2107 | "TX status report missed for entry %d\n", |
2108 | entry_done->entry_idx); | 2108 | entry_done->entry_idx); |
2109 | 2109 | ||
2110 | txdesc.flags = 0; | 2110 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); |
2111 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
2112 | txdesc.retry = 0; | ||
2113 | |||
2114 | rt2x00lib_txdone(entry_done, &txdesc); | ||
2115 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 2111 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
2116 | } | 2112 | } |
2117 | 2113 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 99985a218653..8ca19f70aea7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -929,7 +929,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
929 | /* | 929 | /* |
930 | * Determine r17 bounds. | 930 | * Determine r17 bounds. |
931 | */ | 931 | */ |
932 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 932 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
933 | low_bound = 0x28; | 933 | low_bound = 0x28; |
934 | up_bound = 0x48; | 934 | up_bound = 0x48; |
935 | 935 | ||
@@ -1597,7 +1597,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1597 | return 0; | 1597 | return 0; |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1600 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1601 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { | 1601 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { |
1602 | if (lna == 3 || lna == 2) | 1602 | if (lna == 3 || lna == 2) |
1603 | offset += 10; | 1603 | offset += 10; |