diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 193 |
1 files changed, 100 insertions, 93 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 01125563aba3..f4a951338f8f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -148,20 +148,105 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) | |||
148 | dev_kfree_skb_any(skb); | 148 | dev_kfree_skb_any(skb); |
149 | } | 149 | } |
150 | 150 | ||
151 | static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, | ||
152 | struct txentry_desc *txdesc) | ||
153 | { | ||
154 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | ||
155 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; | ||
156 | struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); | ||
157 | unsigned long irqflags; | ||
158 | |||
159 | if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) || | ||
160 | unlikely(!tx_info->control.vif)) | ||
161 | return; | ||
162 | |||
163 | /* | ||
164 | * Hardware should insert sequence counter. | ||
165 | * FIXME: We insert a software sequence counter first for | ||
166 | * hardware that doesn't support hardware sequence counting. | ||
167 | * | ||
168 | * This is wrong because beacons are not getting sequence | ||
169 | * numbers assigned properly. | ||
170 | * | ||
171 | * A secondary problem exists for drivers that cannot toggle | ||
172 | * sequence counting per-frame, since those will override the | ||
173 | * sequence counter given by mac80211. | ||
174 | */ | ||
175 | spin_lock_irqsave(&intf->seqlock, irqflags); | ||
176 | |||
177 | if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) | ||
178 | intf->seqno += 0x10; | ||
179 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
180 | hdr->seq_ctrl |= cpu_to_le16(intf->seqno); | ||
181 | |||
182 | spin_unlock_irqrestore(&intf->seqlock, irqflags); | ||
183 | |||
184 | __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); | ||
185 | } | ||
186 | |||
187 | static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, | ||
188 | struct txentry_desc *txdesc, | ||
189 | const struct rt2x00_rate *hwrate) | ||
190 | { | ||
191 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | ||
192 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | ||
193 | struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; | ||
194 | unsigned int data_length; | ||
195 | unsigned int duration; | ||
196 | unsigned int residual; | ||
197 | |||
198 | /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */ | ||
199 | data_length = entry->skb->len + 4; | ||
200 | data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb); | ||
201 | |||
202 | /* | ||
203 | * PLCP setup | ||
204 | * Length calculation depends on OFDM/CCK rate. | ||
205 | */ | ||
206 | txdesc->signal = hwrate->plcp; | ||
207 | txdesc->service = 0x04; | ||
208 | |||
209 | if (hwrate->flags & DEV_RATE_OFDM) { | ||
210 | txdesc->length_high = (data_length >> 6) & 0x3f; | ||
211 | txdesc->length_low = data_length & 0x3f; | ||
212 | } else { | ||
213 | /* | ||
214 | * Convert length to microseconds. | ||
215 | */ | ||
216 | residual = GET_DURATION_RES(data_length, hwrate->bitrate); | ||
217 | duration = GET_DURATION(data_length, hwrate->bitrate); | ||
218 | |||
219 | if (residual != 0) { | ||
220 | duration++; | ||
221 | |||
222 | /* | ||
223 | * Check if we need to set the Length Extension | ||
224 | */ | ||
225 | if (hwrate->bitrate == 110 && residual <= 30) | ||
226 | txdesc->service |= 0x80; | ||
227 | } | ||
228 | |||
229 | txdesc->length_high = (duration >> 8) & 0xff; | ||
230 | txdesc->length_low = duration & 0xff; | ||
231 | |||
232 | /* | ||
233 | * When preamble is enabled we should set the | ||
234 | * preamble bit for the signal. | ||
235 | */ | ||
236 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
237 | txdesc->signal |= 0x08; | ||
238 | } | ||
239 | } | ||
240 | |||
151 | static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | 241 | static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, |
152 | struct txentry_desc *txdesc) | 242 | struct txentry_desc *txdesc) |
153 | { | 243 | { |
154 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 244 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
155 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | 245 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); |
156 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; | 246 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; |
157 | struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; | ||
158 | struct ieee80211_rate *rate = | 247 | struct ieee80211_rate *rate = |
159 | ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); | 248 | ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); |
160 | const struct rt2x00_rate *hwrate; | 249 | const struct rt2x00_rate *hwrate; |
161 | unsigned int data_length; | ||
162 | unsigned int duration; | ||
163 | unsigned int residual; | ||
164 | unsigned long irqflags; | ||
165 | 250 | ||
166 | memset(txdesc, 0, sizeof(*txdesc)); | 251 | memset(txdesc, 0, sizeof(*txdesc)); |
167 | 252 | ||
@@ -173,27 +258,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
173 | txdesc->cw_max = entry->queue->cw_max; | 258 | txdesc->cw_max = entry->queue->cw_max; |
174 | txdesc->aifs = entry->queue->aifs; | 259 | txdesc->aifs = entry->queue->aifs; |
175 | 260 | ||
176 | /* Data length + CRC */ | ||
177 | data_length = entry->skb->len + 4; | ||
178 | |||
179 | /* | 261 | /* |
180 | * Check whether this frame is to be acked. | 262 | * Check whether this frame is to be acked. |
181 | */ | 263 | */ |
182 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) | 264 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) |
183 | __set_bit(ENTRY_TXD_ACK, &txdesc->flags); | 265 | __set_bit(ENTRY_TXD_ACK, &txdesc->flags); |
184 | 266 | ||
185 | if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) && | ||
186 | !entry->skb->do_not_encrypt) { | ||
187 | /* Apply crypto specific descriptor information */ | ||
188 | rt2x00crypto_create_tx_descriptor(entry, txdesc); | ||
189 | |||
190 | /* | ||
191 | * Extend frame length to include all encryption overhead | ||
192 | * that will be added by the hardware. | ||
193 | */ | ||
194 | data_length += rt2x00crypto_tx_overhead(tx_info); | ||
195 | } | ||
196 | |||
197 | /* | 267 | /* |
198 | * Check if this is a RTS/CTS frame | 268 | * Check if this is a RTS/CTS frame |
199 | */ | 269 | */ |
@@ -237,86 +307,23 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
237 | * Set ifs to IFS_SIFS when the this is not the first fragment, | 307 | * Set ifs to IFS_SIFS when the this is not the first fragment, |
238 | * or this fragment came after RTS/CTS. | 308 | * or this fragment came after RTS/CTS. |
239 | */ | 309 | */ |
240 | if (test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { | 310 | if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) && |
241 | txdesc->ifs = IFS_SIFS; | 311 | !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { |
242 | } else if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) { | ||
243 | __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); | 312 | __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); |
244 | txdesc->ifs = IFS_BACKOFF; | 313 | txdesc->ifs = IFS_BACKOFF; |
245 | } else { | 314 | } else |
246 | txdesc->ifs = IFS_SIFS; | 315 | txdesc->ifs = IFS_SIFS; |
247 | } | ||
248 | 316 | ||
249 | /* | ||
250 | * Hardware should insert sequence counter. | ||
251 | * FIXME: We insert a software sequence counter first for | ||
252 | * hardware that doesn't support hardware sequence counting. | ||
253 | * | ||
254 | * This is wrong because beacons are not getting sequence | ||
255 | * numbers assigned properly. | ||
256 | * | ||
257 | * A secondary problem exists for drivers that cannot toggle | ||
258 | * sequence counting per-frame, since those will override the | ||
259 | * sequence counter given by mac80211. | ||
260 | */ | ||
261 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
262 | if (likely(tx_info->control.vif)) { | ||
263 | struct rt2x00_intf *intf; | ||
264 | |||
265 | intf = vif_to_intf(tx_info->control.vif); | ||
266 | |||
267 | spin_lock_irqsave(&intf->seqlock, irqflags); | ||
268 | |||
269 | if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) | ||
270 | intf->seqno += 0x10; | ||
271 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
272 | hdr->seq_ctrl |= cpu_to_le16(intf->seqno); | ||
273 | |||
274 | spin_unlock_irqrestore(&intf->seqlock, irqflags); | ||
275 | |||
276 | __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * PLCP setup | ||
282 | * Length calculation depends on OFDM/CCK rate. | ||
283 | */ | ||
284 | hwrate = rt2x00_get_rate(rate->hw_value); | 317 | hwrate = rt2x00_get_rate(rate->hw_value); |
285 | txdesc->signal = hwrate->plcp; | 318 | if (hwrate->flags & DEV_RATE_OFDM) |
286 | txdesc->service = 0x04; | ||
287 | |||
288 | if (hwrate->flags & DEV_RATE_OFDM) { | ||
289 | __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags); | 319 | __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags); |
290 | 320 | ||
291 | txdesc->length_high = (data_length >> 6) & 0x3f; | 321 | /* |
292 | txdesc->length_low = data_length & 0x3f; | 322 | * Apply TX descriptor handling by components |
293 | } else { | 323 | */ |
294 | /* | 324 | rt2x00crypto_create_tx_descriptor(entry, txdesc); |
295 | * Convert length to microseconds. | 325 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); |
296 | */ | 326 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); |
297 | residual = GET_DURATION_RES(data_length, hwrate->bitrate); | ||
298 | duration = GET_DURATION(data_length, hwrate->bitrate); | ||
299 | |||
300 | if (residual != 0) { | ||
301 | duration++; | ||
302 | |||
303 | /* | ||
304 | * Check if we need to set the Length Extension | ||
305 | */ | ||
306 | if (hwrate->bitrate == 110 && residual <= 30) | ||
307 | txdesc->service |= 0x80; | ||
308 | } | ||
309 | |||
310 | txdesc->length_high = (duration >> 8) & 0xff; | ||
311 | txdesc->length_low = duration & 0xff; | ||
312 | |||
313 | /* | ||
314 | * When preamble is enabled we should set the | ||
315 | * preamble bit for the signal. | ||
316 | */ | ||
317 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
318 | txdesc->signal |= 0x08; | ||
319 | } | ||
320 | } | 327 | } |
321 | 328 | ||
322 | static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | 329 | static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, |