aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00queue.c
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/wireless/rt2x00/rt2x00queue.c
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/wireless/rt2x00/rt2x00queue.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c157
1 files changed, 157 insertions, 0 deletions
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{