aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-05-10 07:46:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:47:34 -0400
commit7050ec821c52826b63835dde54ee3d71c7db4262 (patch)
treef8154413b4ed1e8ff01b6dbb1c79240dcce83dc8 /drivers/net
parent4de36fe5abe077a4c65bf0b6a309865aa043e055 (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')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h42
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c148
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c157
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c11
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(&reg, TXRX_CSR19_BEACON_GEN, 0); 1722 rt2x00_set_field16(&reg, 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 */
945void 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 */
961void 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 */
969void 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 */
976int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, 1004int 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,
612EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); 612EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
613 613
614/* 614/*
615 * TX descriptor initializer
616 */
617void 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}
760EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
761
762/*
763 * Driver initialization handlers. 615 * Driver initialization handlers.
764 */ 616 */
765const struct rt2x00_rate rt2x00_supported_rates[12] = { 617const 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
32void 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}
161EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor);
162
163void 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}
187EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor);
188
32struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, 189struct 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 */
214enum txentry_desc_flags { 215enum 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
2363static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, 2363static 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,