diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-05-10 07:46:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-05-21 21:47:34 -0400 |
commit | 7050ec821c52826b63835dde54ee3d71c7db4262 (patch) | |
tree | f8154413b4ed1e8ff01b6dbb1c79240dcce83dc8 /drivers/net/wireless/rt2x00 | |
parent | 4de36fe5abe077a4c65bf0b6a309865aa043e055 (diff) |
rt2x00: Split rt2x00lib_write_tx_desc()
Split rt2x00lib_write_tx_desc() up into a TX descriptor initializor
and TX descriptor writer.
This split is required to properly allow mac80211 to move its
tx_control structure into the skb->cb array.
The rt2x00queue_create_tx_descriptor() function will read all tx control
information and convert it into a rt2x00 TX descriptor information structure.
After that function is complete, we have all information we needed from the
tx control structure and are free to start writing into the skb->cb array
for our own purposes.
rt2x00queue_write_tx_descriptor() will be in charge of really sending
the TX descriptor to the hardware and kicking the TX queue.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2400pci.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500pci.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 42 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 148 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00pci.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 157 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt61pci.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 11 |
11 files changed, 265 insertions, 163 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 2c0cf394c78e..d3d9b189fd83 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -1492,6 +1492,7 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1492 | struct rt2x00_intf *intf = vif_to_intf(control->vif); | 1492 | struct rt2x00_intf *intf = vif_to_intf(control->vif); |
1493 | struct queue_entry_priv_pci_tx *priv_tx; | 1493 | struct queue_entry_priv_pci_tx *priv_tx; |
1494 | struct skb_frame_desc *skbdesc; | 1494 | struct skb_frame_desc *skbdesc; |
1495 | struct txentry_desc txdesc; | ||
1495 | u32 reg; | 1496 | u32 reg; |
1496 | 1497 | ||
1497 | if (unlikely(!intf->beacon)) | 1498 | if (unlikely(!intf->beacon)) |
@@ -1499,6 +1500,14 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1499 | priv_tx = intf->beacon->priv_data; | 1500 | priv_tx = intf->beacon->priv_data; |
1500 | 1501 | ||
1501 | /* | 1502 | /* |
1503 | * Copy all TX descriptor information into txdesc, | ||
1504 | * after that we are free to use the skb->cb array | ||
1505 | * for our information. | ||
1506 | */ | ||
1507 | intf->beacon->skb = skb; | ||
1508 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control); | ||
1509 | |||
1510 | /* | ||
1502 | * Fill in skb descriptor | 1511 | * Fill in skb descriptor |
1503 | */ | 1512 | */ |
1504 | skbdesc = get_skb_frame_desc(skb); | 1513 | skbdesc = get_skb_frame_desc(skb); |
@@ -1525,8 +1534,8 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1525 | * Write entire beacon with descriptor to register, | 1534 | * Write entire beacon with descriptor to register, |
1526 | * and kick the beacon generator. | 1535 | * and kick the beacon generator. |
1527 | */ | 1536 | */ |
1528 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | ||
1529 | memcpy(priv_tx->data, skb->data, skb->len); | 1537 | memcpy(priv_tx->data, skb->data, skb->len); |
1538 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
1530 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | 1539 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); |
1531 | 1540 | ||
1532 | return 0; | 1541 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 6c31c5db0ca1..7de7980738f1 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1808,6 +1808,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1808 | struct rt2x00_intf *intf = vif_to_intf(control->vif); | 1808 | struct rt2x00_intf *intf = vif_to_intf(control->vif); |
1809 | struct queue_entry_priv_pci_tx *priv_tx; | 1809 | struct queue_entry_priv_pci_tx *priv_tx; |
1810 | struct skb_frame_desc *skbdesc; | 1810 | struct skb_frame_desc *skbdesc; |
1811 | struct txentry_desc txdesc; | ||
1811 | u32 reg; | 1812 | u32 reg; |
1812 | 1813 | ||
1813 | if (unlikely(!intf->beacon)) | 1814 | if (unlikely(!intf->beacon)) |
@@ -1816,6 +1817,14 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1816 | priv_tx = intf->beacon->priv_data; | 1817 | priv_tx = intf->beacon->priv_data; |
1817 | 1818 | ||
1818 | /* | 1819 | /* |
1820 | * Copy all TX descriptor information into txdesc, | ||
1821 | * after that we are free to use the skb->cb array | ||
1822 | * for our information. | ||
1823 | */ | ||
1824 | intf->beacon->skb = skb; | ||
1825 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control); | ||
1826 | |||
1827 | /* | ||
1819 | * Fill in skb descriptor | 1828 | * Fill in skb descriptor |
1820 | */ | 1829 | */ |
1821 | skbdesc = get_skb_frame_desc(skb); | 1830 | skbdesc = get_skb_frame_desc(skb); |
@@ -1842,8 +1851,8 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1842 | * Write entire beacon with descriptor to register, | 1851 | * Write entire beacon with descriptor to register, |
1843 | * and kick the beacon generator. | 1852 | * and kick the beacon generator. |
1844 | */ | 1853 | */ |
1845 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | ||
1846 | memcpy(priv_tx->data, skb->data, skb->len); | 1854 | memcpy(priv_tx->data, skb->data, skb->len); |
1855 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); | ||
1847 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); | 1856 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); |
1848 | 1857 | ||
1849 | return 0; | 1858 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3be4c7ea8dd1..6fe713a1d758 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1676,6 +1676,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, | |||
1676 | struct rt2x00_intf *intf = vif_to_intf(control->vif); | 1676 | struct rt2x00_intf *intf = vif_to_intf(control->vif); |
1677 | struct queue_entry_priv_usb_bcn *priv_bcn; | 1677 | struct queue_entry_priv_usb_bcn *priv_bcn; |
1678 | struct skb_frame_desc *skbdesc; | 1678 | struct skb_frame_desc *skbdesc; |
1679 | struct txentry_desc txdesc; | ||
1679 | int pipe = usb_sndbulkpipe(usb_dev, 1); | 1680 | int pipe = usb_sndbulkpipe(usb_dev, 1); |
1680 | int length; | 1681 | int length; |
1681 | u16 reg; | 1682 | u16 reg; |
@@ -1686,6 +1687,14 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, | |||
1686 | priv_bcn = intf->beacon->priv_data; | 1687 | priv_bcn = intf->beacon->priv_data; |
1687 | 1688 | ||
1688 | /* | 1689 | /* |
1690 | * Copy all TX descriptor information into txdesc, | ||
1691 | * after that we are free to use the skb->cb array | ||
1692 | * for our information. | ||
1693 | */ | ||
1694 | intf->beacon->skb = skb; | ||
1695 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control); | ||
1696 | |||
1697 | /* | ||
1689 | * Add the descriptor in front of the skb. | 1698 | * Add the descriptor in front of the skb. |
1690 | */ | 1699 | */ |
1691 | skb_push(skb, intf->beacon->queue->desc_size); | 1700 | skb_push(skb, intf->beacon->queue->desc_size); |
@@ -1713,7 +1722,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, | |||
1713 | rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); | 1722 | rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); |
1714 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); | 1723 | rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); |
1715 | 1724 | ||
1716 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | 1725 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); |
1717 | 1726 | ||
1718 | /* | 1727 | /* |
1719 | * USB devices cannot blindly pass the skb->len as the | 1728 | * USB devices cannot blindly pass the skb->len as the |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6f7b34fac16c..9c186d79c11c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -927,6 +927,41 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) | |||
927 | } | 927 | } |
928 | 928 | ||
929 | /** | 929 | /** |
930 | * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input | ||
931 | * @entry: The entry which will be used to transfer the TX frame. | ||
932 | * @txdesc: rt2x00 TX descriptor which will be initialized by this function. | ||
933 | * @control: mac80211 TX control structure from where we read the information. | ||
934 | * | ||
935 | * This function will initialize the &struct txentry_desc based on information | ||
936 | * from mac80211. This descriptor can then be used by rt2x00lib and the drivers | ||
937 | * to correctly initialize the hardware descriptor. | ||
938 | * Note that before calling this function the skb->cb array must be untouched | ||
939 | * by rt2x00lib. Only after this function completes will it be save to | ||
940 | * overwrite the skb->cb information. | ||
941 | * The reason for this is that mac80211 writes its own tx information into | ||
942 | * the skb->cb array, and this function will use that information to initialize | ||
943 | * the &struct txentry_desc structure. | ||
944 | */ | ||
945 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | ||
946 | struct txentry_desc *txdesc, | ||
947 | struct ieee80211_tx_control *control); | ||
948 | |||
949 | /** | ||
950 | * rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware | ||
951 | * @entry: The entry which will be used to transfer the TX frame. | ||
952 | * @txdesc: TX descriptor which will be used to write hardware descriptor | ||
953 | * | ||
954 | * This function will write a TX descriptor initialized by | ||
955 | * &rt2x00queue_create_tx_descriptor to the hardware. After this call | ||
956 | * has completed the frame is now owned by the hardware, the hardware | ||
957 | * queue will have automatically be kicked unless this frame was generated | ||
958 | * by rt2x00lib, in which case the frame is "special" and must be kicked | ||
959 | * by the caller. | ||
960 | */ | ||
961 | void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | ||
962 | struct txentry_desc *txdesc); | ||
963 | |||
964 | /** | ||
930 | * rt2x00queue_get_queue - Convert queue index to queue pointer | 965 | * rt2x00queue_get_queue - Convert queue index to queue pointer |
931 | * @rt2x00dev: Pointer to &struct rt2x00_dev. | 966 | * @rt2x00dev: Pointer to &struct rt2x00_dev. |
932 | * @queue: rt2x00 queue index (see &enum data_queue_qid). | 967 | * @queue: rt2x00 queue index (see &enum data_queue_qid). |
@@ -964,13 +999,6 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
964 | struct rxdone_entry_desc *rxdesc); | 999 | struct rxdone_entry_desc *rxdesc); |
965 | 1000 | ||
966 | /* | 1001 | /* |
967 | * TX descriptor initializer | ||
968 | */ | ||
969 | void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, | ||
970 | struct sk_buff *skb, | ||
971 | struct ieee80211_tx_control *control); | ||
972 | |||
973 | /* | ||
974 | * mac80211 handlers. | 1002 | * mac80211 handlers. |
975 | */ | 1003 | */ |
976 | int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, | 1004 | int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 46c377873f16..171f445962db 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -612,154 +612,6 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
612 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | 612 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); |
613 | 613 | ||
614 | /* | 614 | /* |
615 | * TX descriptor initializer | ||
616 | */ | ||
617 | void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, | ||
618 | struct sk_buff *skb, | ||
619 | struct ieee80211_tx_control *control) | ||
620 | { | ||
621 | struct txentry_desc txdesc; | ||
622 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | ||
623 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data; | ||
624 | const struct rt2x00_rate *rate; | ||
625 | int tx_rate; | ||
626 | int length; | ||
627 | int duration; | ||
628 | int residual; | ||
629 | u16 frame_control; | ||
630 | u16 seq_ctrl; | ||
631 | |||
632 | memset(&txdesc, 0, sizeof(txdesc)); | ||
633 | |||
634 | txdesc.queue = skbdesc->entry->queue->qid; | ||
635 | txdesc.cw_min = skbdesc->entry->queue->cw_min; | ||
636 | txdesc.cw_max = skbdesc->entry->queue->cw_max; | ||
637 | txdesc.aifs = skbdesc->entry->queue->aifs; | ||
638 | |||
639 | /* | ||
640 | * Read required fields from ieee80211 header. | ||
641 | */ | ||
642 | frame_control = le16_to_cpu(hdr->frame_control); | ||
643 | seq_ctrl = le16_to_cpu(hdr->seq_ctrl); | ||
644 | |||
645 | tx_rate = control->tx_rate->hw_value; | ||
646 | |||
647 | /* | ||
648 | * Check whether this frame is to be acked | ||
649 | */ | ||
650 | if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) | ||
651 | __set_bit(ENTRY_TXD_ACK, &txdesc.flags); | ||
652 | |||
653 | /* | ||
654 | * Check if this is a RTS/CTS frame | ||
655 | */ | ||
656 | if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { | ||
657 | __set_bit(ENTRY_TXD_BURST, &txdesc.flags); | ||
658 | if (is_rts_frame(frame_control)) { | ||
659 | __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags); | ||
660 | __set_bit(ENTRY_TXD_ACK, &txdesc.flags); | ||
661 | } else | ||
662 | __clear_bit(ENTRY_TXD_ACK, &txdesc.flags); | ||
663 | if (control->rts_cts_rate) | ||
664 | tx_rate = control->rts_cts_rate->hw_value; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * Determine retry information. | ||
669 | */ | ||
670 | txdesc.retry_limit = control->retry_limit; | ||
671 | if (control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) | ||
672 | __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc.flags); | ||
673 | |||
674 | /* | ||
675 | * Check if more fragments are pending | ||
676 | */ | ||
677 | if (ieee80211_get_morefrag(hdr)) { | ||
678 | __set_bit(ENTRY_TXD_BURST, &txdesc.flags); | ||
679 | __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags); | ||
680 | } | ||
681 | |||
682 | /* | ||
683 | * Beacons and probe responses require the tsf timestamp | ||
684 | * to be inserted into the frame. | ||
685 | */ | ||
686 | if (txdesc.queue == QID_BEACON || is_probe_resp(frame_control)) | ||
687 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags); | ||
688 | |||
689 | /* | ||
690 | * Determine with what IFS priority this frame should be send. | ||
691 | * Set ifs to IFS_SIFS when the this is not the first fragment, | ||
692 | * or this fragment came after RTS/CTS. | ||
693 | */ | ||
694 | if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags)) { | ||
695 | txdesc.ifs = IFS_SIFS; | ||
696 | } else if (control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) { | ||
697 | __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc.flags); | ||
698 | txdesc.ifs = IFS_BACKOFF; | ||
699 | } else { | ||
700 | txdesc.ifs = IFS_SIFS; | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * PLCP setup | ||
705 | * Length calculation depends on OFDM/CCK rate. | ||
706 | */ | ||
707 | rate = rt2x00_get_rate(tx_rate); | ||
708 | txdesc.signal = rate->plcp; | ||
709 | txdesc.service = 0x04; | ||
710 | |||
711 | length = skbdesc->data_len + FCS_LEN; | ||
712 | if (rate->flags & DEV_RATE_OFDM) { | ||
713 | __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); | ||
714 | |||
715 | txdesc.length_high = (length >> 6) & 0x3f; | ||
716 | txdesc.length_low = length & 0x3f; | ||
717 | } else { | ||
718 | /* | ||
719 | * Convert length to microseconds. | ||
720 | */ | ||
721 | residual = get_duration_res(length, rate->bitrate); | ||
722 | duration = get_duration(length, rate->bitrate); | ||
723 | |||
724 | if (residual != 0) { | ||
725 | duration++; | ||
726 | |||
727 | /* | ||
728 | * Check if we need to set the Length Extension | ||
729 | */ | ||
730 | if (rate->bitrate == 110 && residual <= 30) | ||
731 | txdesc.service |= 0x80; | ||
732 | } | ||
733 | |||
734 | txdesc.length_high = (duration >> 8) & 0xff; | ||
735 | txdesc.length_low = duration & 0xff; | ||
736 | |||
737 | /* | ||
738 | * When preamble is enabled we should set the | ||
739 | * preamble bit for the signal. | ||
740 | */ | ||
741 | if (rt2x00_get_rate_preamble(tx_rate)) | ||
742 | txdesc.signal |= 0x08; | ||
743 | } | ||
744 | |||
745 | rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc); | ||
746 | |||
747 | /* | ||
748 | * Update queue entry. | ||
749 | */ | ||
750 | skbdesc->entry->skb = skb; | ||
751 | |||
752 | /* | ||
753 | * The frame has been completely initialized and ready | ||
754 | * for sending to the device. The caller will push the | ||
755 | * frame to the device, but we are going to push the | ||
756 | * frame to debugfs here. | ||
757 | */ | ||
758 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, skb); | ||
759 | } | ||
760 | EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); | ||
761 | |||
762 | /* | ||
763 | * Driver initialization handlers. | 615 | * Driver initialization handlers. |
764 | */ | 616 | */ |
765 | const struct rt2x00_rate rt2x00_supported_rates[12] = { | 617 | const struct rt2x00_rate rt2x00_supported_rates[12] = { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index c17078eac197..a056b12fbd1c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -41,6 +41,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
41 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 41 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
42 | struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; | 42 | struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; |
43 | struct skb_frame_desc *skbdesc; | 43 | struct skb_frame_desc *skbdesc; |
44 | struct txentry_desc txdesc; | ||
44 | u32 word; | 45 | u32 word; |
45 | 46 | ||
46 | if (rt2x00queue_full(queue)) | 47 | if (rt2x00queue_full(queue)) |
@@ -58,6 +59,14 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
58 | } | 59 | } |
59 | 60 | ||
60 | /* | 61 | /* |
62 | * Copy all TX descriptor information into txdesc, | ||
63 | * after that we are free to use the skb->cb array | ||
64 | * for our information. | ||
65 | */ | ||
66 | entry->skb = skb; | ||
67 | rt2x00queue_create_tx_descriptor(entry, &txdesc, control); | ||
68 | |||
69 | /* | ||
61 | * Fill in skb descriptor | 70 | * Fill in skb descriptor |
62 | */ | 71 | */ |
63 | skbdesc = get_skb_frame_desc(skb); | 72 | skbdesc = get_skb_frame_desc(skb); |
@@ -69,8 +78,8 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
69 | 78 | ||
70 | memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); | 79 | memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); |
71 | memcpy(priv_tx->data, skb->data, skb->len); | 80 | memcpy(priv_tx->data, skb->data, skb->len); |
72 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | ||
73 | 81 | ||
82 | rt2x00queue_write_tx_descriptor(entry, &txdesc); | ||
74 | rt2x00queue_index_inc(queue, Q_INDEX); | 83 | rt2x00queue_index_inc(queue, Q_INDEX); |
75 | 84 | ||
76 | return 0; | 85 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 95f8dd3462f6..19c10629c767 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -29,6 +29,163 @@ | |||
29 | #include "rt2x00.h" | 29 | #include "rt2x00.h" |
30 | #include "rt2x00lib.h" | 30 | #include "rt2x00lib.h" |
31 | 31 | ||
32 | void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | ||
33 | struct txentry_desc *txdesc, | ||
34 | struct ieee80211_tx_control *control) | ||
35 | { | ||
36 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; | ||
37 | struct ieee80211_rate *rate = control->tx_rate; | ||
38 | const struct rt2x00_rate *hwrate; | ||
39 | unsigned int data_length; | ||
40 | unsigned int duration; | ||
41 | unsigned int residual; | ||
42 | u16 frame_control; | ||
43 | |||
44 | memset(txdesc, 0, sizeof(*txdesc)); | ||
45 | |||
46 | /* | ||
47 | * Initialize information from queue | ||
48 | */ | ||
49 | txdesc->queue = entry->queue->qid; | ||
50 | txdesc->cw_min = entry->queue->cw_min; | ||
51 | txdesc->cw_max = entry->queue->cw_max; | ||
52 | txdesc->aifs = entry->queue->aifs; | ||
53 | |||
54 | /* Data length should be extended with 4 bytes for CRC */ | ||
55 | data_length = entry->skb->len + 4; | ||
56 | |||
57 | /* | ||
58 | * Read required fields from ieee80211 header. | ||
59 | */ | ||
60 | frame_control = le16_to_cpu(hdr->frame_control); | ||
61 | |||
62 | /* | ||
63 | * Check whether this frame is to be acked. | ||
64 | */ | ||
65 | if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) | ||
66 | __set_bit(ENTRY_TXD_ACK, &txdesc->flags); | ||
67 | |||
68 | /* | ||
69 | * Check if this is a RTS/CTS frame | ||
70 | */ | ||
71 | if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { | ||
72 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | ||
73 | if (is_rts_frame(frame_control)) { | ||
74 | __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags); | ||
75 | __set_bit(ENTRY_TXD_ACK, &txdesc->flags); | ||
76 | } else { | ||
77 | __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags); | ||
78 | __clear_bit(ENTRY_TXD_ACK, &txdesc->flags); | ||
79 | } | ||
80 | if (control->rts_cts_rate) | ||
81 | rate = control->rts_cts_rate; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Determine retry information. | ||
86 | */ | ||
87 | txdesc->retry_limit = control->retry_limit; | ||
88 | if (control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT) | ||
89 | __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags); | ||
90 | |||
91 | /* | ||
92 | * Check if more fragments are pending | ||
93 | */ | ||
94 | if (ieee80211_get_morefrag(hdr)) { | ||
95 | __set_bit(ENTRY_TXD_BURST, &txdesc->flags); | ||
96 | __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Beacons and probe responses require the tsf timestamp | ||
101 | * to be inserted into the frame. | ||
102 | */ | ||
103 | if (txdesc->queue == QID_BEACON || is_probe_resp(frame_control)) | ||
104 | __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); | ||
105 | |||
106 | /* | ||
107 | * Determine with what IFS priority this frame should be send. | ||
108 | * Set ifs to IFS_SIFS when the this is not the first fragment, | ||
109 | * or this fragment came after RTS/CTS. | ||
110 | */ | ||
111 | if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { | ||
112 | txdesc->ifs = IFS_SIFS; | ||
113 | } else if (control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT) { | ||
114 | __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); | ||
115 | txdesc->ifs = IFS_BACKOFF; | ||
116 | } else { | ||
117 | txdesc->ifs = IFS_SIFS; | ||
118 | } | ||
119 | |||
120 | /* | ||
121 | * PLCP setup | ||
122 | * Length calculation depends on OFDM/CCK rate. | ||
123 | */ | ||
124 | hwrate = rt2x00_get_rate(rate->hw_value); | ||
125 | txdesc->signal = hwrate->plcp; | ||
126 | txdesc->service = 0x04; | ||
127 | |||
128 | if (hwrate->flags & DEV_RATE_OFDM) { | ||
129 | __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags); | ||
130 | |||
131 | txdesc->length_high = (data_length >> 6) & 0x3f; | ||
132 | txdesc->length_low = data_length & 0x3f; | ||
133 | } else { | ||
134 | /* | ||
135 | * Convert length to microseconds. | ||
136 | */ | ||
137 | residual = get_duration_res(data_length, hwrate->bitrate); | ||
138 | duration = get_duration(data_length, hwrate->bitrate); | ||
139 | |||
140 | if (residual != 0) { | ||
141 | duration++; | ||
142 | |||
143 | /* | ||
144 | * Check if we need to set the Length Extension | ||
145 | */ | ||
146 | if (hwrate->bitrate == 110 && residual <= 30) | ||
147 | txdesc->service |= 0x80; | ||
148 | } | ||
149 | |||
150 | txdesc->length_high = (duration >> 8) & 0xff; | ||
151 | txdesc->length_low = duration & 0xff; | ||
152 | |||
153 | /* | ||
154 | * When preamble is enabled we should set the | ||
155 | * preamble bit for the signal. | ||
156 | */ | ||
157 | if (rt2x00_get_rate_preamble(rate->hw_value)) | ||
158 | txdesc->signal |= 0x08; | ||
159 | } | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor); | ||
162 | |||
163 | void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | ||
164 | struct txentry_desc *txdesc) | ||
165 | { | ||
166 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
167 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
168 | |||
169 | rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); | ||
170 | |||
171 | /* | ||
172 | * All processing on the frame has been completed, this means | ||
173 | * it is now ready to be dumped to userspace through debugfs. | ||
174 | */ | ||
175 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); | ||
176 | |||
177 | /* | ||
178 | * We are done writing the frame to the queue entry, | ||
179 | * if this entry is a RTS of CTS-to-self frame we are done, | ||
180 | * otherwise we need to kick the queue. | ||
181 | */ | ||
182 | if (rt2x00dev->ops->lib->kick_tx_queue && | ||
183 | !(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED)) | ||
184 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, | ||
185 | entry->queue->qid); | ||
186 | } | ||
187 | EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor); | ||
188 | |||
32 | struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, | 189 | struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, |
33 | const enum data_queue_qid queue) | 190 | const enum data_queue_qid queue) |
34 | { | 191 | { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4bde98ba3c60..c6edc52873c4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -203,6 +203,7 @@ struct txdone_entry_desc { | |||
203 | * enum txentry_desc_flags: Status flags for TX entry descriptor | 203 | * enum txentry_desc_flags: Status flags for TX entry descriptor |
204 | * | 204 | * |
205 | * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame. | 205 | * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame. |
206 | * @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame. | ||
206 | * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate. | 207 | * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate. |
207 | * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame. | 208 | * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame. |
208 | * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment. | 209 | * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment. |
@@ -213,6 +214,7 @@ struct txdone_entry_desc { | |||
213 | */ | 214 | */ |
214 | enum txentry_desc_flags { | 215 | enum txentry_desc_flags { |
215 | ENTRY_TXD_RTS_FRAME, | 216 | ENTRY_TXD_RTS_FRAME, |
217 | ENTRY_TXD_CTS_FRAME, | ||
216 | ENTRY_TXD_OFDM_RATE, | 218 | ENTRY_TXD_OFDM_RATE, |
217 | ENTRY_TXD_FIRST_FRAGMENT, | 219 | ENTRY_TXD_FIRST_FRAGMENT, |
218 | ENTRY_TXD_MORE_FRAG, | 220 | ENTRY_TXD_MORE_FRAG, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index f72b3d07a42d..df6621025f4b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -186,6 +186,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
186 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 186 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
187 | struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; | 187 | struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; |
188 | struct skb_frame_desc *skbdesc; | 188 | struct skb_frame_desc *skbdesc; |
189 | struct txentry_desc txdesc; | ||
189 | u32 length; | 190 | u32 length; |
190 | 191 | ||
191 | if (rt2x00queue_full(queue)) | 192 | if (rt2x00queue_full(queue)) |
@@ -200,6 +201,14 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
200 | } | 201 | } |
201 | 202 | ||
202 | /* | 203 | /* |
204 | * Copy all TX descriptor information into txdesc, | ||
205 | * after that we are free to use the skb->cb array | ||
206 | * for our information. | ||
207 | */ | ||
208 | entry->skb = skb; | ||
209 | rt2x00queue_create_tx_descriptor(entry, &txdesc, control); | ||
210 | |||
211 | /* | ||
203 | * Add the descriptor in front of the skb. | 212 | * Add the descriptor in front of the skb. |
204 | */ | 213 | */ |
205 | skb_push(skb, queue->desc_size); | 214 | skb_push(skb, queue->desc_size); |
@@ -216,7 +225,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, | |||
216 | skbdesc->entry = entry; | 225 | skbdesc->entry = entry; |
217 | 226 | ||
218 | memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); | 227 | memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); |
219 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | 228 | rt2x00queue_write_tx_descriptor(entry, &txdesc); |
220 | 229 | ||
221 | /* | 230 | /* |
222 | * USB devices cannot blindly pass the skb->len as the | 231 | * USB devices cannot blindly pass the skb->len as the |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index d8e681ec4bb0..d01d5f16bbce 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2361,18 +2361,27 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) | |||
2361 | } | 2361 | } |
2362 | 2362 | ||
2363 | static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | 2363 | static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, |
2364 | struct ieee80211_tx_control *control) | 2364 | struct ieee80211_tx_control *control) |
2365 | { | 2365 | { |
2366 | struct rt2x00_dev *rt2x00dev = hw->priv; | 2366 | struct rt2x00_dev *rt2x00dev = hw->priv; |
2367 | struct rt2x00_intf *intf = vif_to_intf(control->vif); | 2367 | struct rt2x00_intf *intf = vif_to_intf(control->vif); |
2368 | struct queue_entry_priv_pci_tx *priv_tx; | 2368 | struct queue_entry_priv_pci_tx *priv_tx; |
2369 | struct skb_frame_desc *skbdesc; | 2369 | struct skb_frame_desc *skbdesc; |
2370 | struct txentry_desc txdesc; | ||
2370 | unsigned int beacon_base; | 2371 | unsigned int beacon_base; |
2371 | u32 reg; | 2372 | u32 reg; |
2372 | 2373 | ||
2373 | if (unlikely(!intf->beacon)) | 2374 | if (unlikely(!intf->beacon)) |
2374 | return -ENOBUFS; | 2375 | return -ENOBUFS; |
2375 | 2376 | ||
2377 | /* | ||
2378 | * Copy all TX descriptor information into txdesc, | ||
2379 | * after that we are free to use the skb->cb array | ||
2380 | * for our information. | ||
2381 | */ | ||
2382 | intf->beacon->skb = skb; | ||
2383 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control); | ||
2384 | |||
2376 | priv_tx = intf->beacon->priv_data; | 2385 | priv_tx = intf->beacon->priv_data; |
2377 | memset(priv_tx->desc, 0, intf->beacon->queue->desc_size); | 2386 | memset(priv_tx->desc, 0, intf->beacon->queue->desc_size); |
2378 | 2387 | ||
@@ -2402,7 +2411,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2402 | * Write entire beacon with descriptor to register, | 2411 | * Write entire beacon with descriptor to register, |
2403 | * and kick the beacon generator. | 2412 | * and kick the beacon generator. |
2404 | */ | 2413 | */ |
2405 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | 2414 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); |
2406 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | 2415 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); |
2407 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, | 2416 | rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, |
2408 | skbdesc->desc, skbdesc->desc_len); | 2417 | skbdesc->desc, skbdesc->desc_len); |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1bcf8c132cdc..bc44116a8a3e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1956,6 +1956,7 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1956 | struct rt2x00_dev *rt2x00dev = hw->priv; | 1956 | struct rt2x00_dev *rt2x00dev = hw->priv; |
1957 | struct rt2x00_intf *intf = vif_to_intf(control->vif); | 1957 | struct rt2x00_intf *intf = vif_to_intf(control->vif); |
1958 | struct skb_frame_desc *skbdesc; | 1958 | struct skb_frame_desc *skbdesc; |
1959 | struct txentry_desc txdesc; | ||
1959 | unsigned int beacon_base; | 1960 | unsigned int beacon_base; |
1960 | u32 reg; | 1961 | u32 reg; |
1961 | 1962 | ||
@@ -1963,6 +1964,14 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1963 | return -ENOBUFS; | 1964 | return -ENOBUFS; |
1964 | 1965 | ||
1965 | /* | 1966 | /* |
1967 | * Copy all TX descriptor information into txdesc, | ||
1968 | * after that we are free to use the skb->cb array | ||
1969 | * for our information. | ||
1970 | */ | ||
1971 | intf->beacon->skb = skb; | ||
1972 | rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc, control); | ||
1973 | |||
1974 | /* | ||
1966 | * Add the descriptor in front of the skb. | 1975 | * Add the descriptor in front of the skb. |
1967 | */ | 1976 | */ |
1968 | skb_push(skb, intf->beacon->queue->desc_size); | 1977 | skb_push(skb, intf->beacon->queue->desc_size); |
@@ -1994,7 +2003,7 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1994 | * Write entire beacon with descriptor to register, | 2003 | * Write entire beacon with descriptor to register, |
1995 | * and kick the beacon generator. | 2004 | * and kick the beacon generator. |
1996 | */ | 2005 | */ |
1997 | rt2x00lib_write_tx_desc(rt2x00dev, skb, control); | 2006 | rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); |
1998 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | 2007 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); |
1999 | rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, | 2008 | rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, |
2000 | USB_VENDOR_REQUEST_OUT, beacon_base, 0, | 2009 | USB_VENDOR_REQUEST_OUT, beacon_base, 0, |