diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 48 |
1 files changed, 42 insertions, 6 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a5664bd8493e..44e5b3279ca7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -148,6 +148,35 @@ 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 | void rt2x00queue_payload_align(struct sk_buff *skb, | ||
152 | bool l2pad, unsigned int header_length) | ||
153 | { | ||
154 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); | ||
155 | unsigned int frame_length = skb->len; | ||
156 | unsigned int align = ALIGN_SIZE(skb, header_length); | ||
157 | |||
158 | if (!align) | ||
159 | return; | ||
160 | |||
161 | if (l2pad) { | ||
162 | if (skbdesc->flags & SKBDESC_L2_PADDED) { | ||
163 | /* Remove L2 padding */ | ||
164 | memmove(skb->data + align, skb->data, header_length); | ||
165 | skb_pull(skb, align); | ||
166 | skbdesc->flags &= ~SKBDESC_L2_PADDED; | ||
167 | } else { | ||
168 | /* Add L2 padding */ | ||
169 | skb_push(skb, align); | ||
170 | memmove(skb->data, skb->data + align, header_length); | ||
171 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
172 | } | ||
173 | } else { | ||
174 | /* Generic payload alignment to 4-byte boundary */ | ||
175 | skb_push(skb, align); | ||
176 | memmove(skb->data, skb->data + align, frame_length); | ||
177 | } | ||
178 | } | ||
179 | |||
151 | static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, | 180 | static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, |
152 | struct txentry_desc *txdesc) | 181 | struct txentry_desc *txdesc) |
153 | { | 182 | { |
@@ -259,6 +288,12 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
259 | txdesc->aifs = entry->queue->aifs; | 288 | txdesc->aifs = entry->queue->aifs; |
260 | 289 | ||
261 | /* | 290 | /* |
291 | * Header and alignment information. | ||
292 | */ | ||
293 | txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
294 | txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); | ||
295 | |||
296 | /* | ||
262 | * Check whether this frame is to be acked. | 297 | * Check whether this frame is to be acked. |
263 | */ | 298 | */ |
264 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) | 299 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) |
@@ -326,6 +361,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, | |||
326 | * Apply TX descriptor handling by components | 361 | * Apply TX descriptor handling by components |
327 | */ | 362 | */ |
328 | rt2x00crypto_create_tx_descriptor(entry, txdesc); | 363 | rt2x00crypto_create_tx_descriptor(entry, txdesc); |
364 | rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); | ||
329 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); | 365 | rt2x00queue_create_tx_descriptor_seq(entry, txdesc); |
330 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); | 366 | rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); |
331 | } | 367 | } |
@@ -368,7 +404,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
368 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 404 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
369 | struct txentry_desc txdesc; | 405 | struct txentry_desc txdesc; |
370 | struct skb_frame_desc *skbdesc; | 406 | struct skb_frame_desc *skbdesc; |
371 | unsigned int iv_len = 0; | ||
372 | u8 rate_idx, rate_flags; | 407 | u8 rate_idx, rate_flags; |
373 | 408 | ||
374 | if (unlikely(rt2x00queue_full(queue))) | 409 | if (unlikely(rt2x00queue_full(queue))) |
@@ -390,9 +425,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
390 | entry->skb = skb; | 425 | entry->skb = skb; |
391 | rt2x00queue_create_tx_descriptor(entry, &txdesc); | 426 | rt2x00queue_create_tx_descriptor(entry, &txdesc); |
392 | 427 | ||
393 | if (IEEE80211_SKB_CB(skb)->control.hw_key != NULL) | ||
394 | iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; | ||
395 | |||
396 | /* | 428 | /* |
397 | * All information is retrieved from the skb->cb array, | 429 | * All information is retrieved from the skb->cb array, |
398 | * now we should claim ownership of the driver part of that | 430 | * now we should claim ownership of the driver part of that |
@@ -415,11 +447,15 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
415 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && | 447 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && |
416 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { | 448 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { |
417 | if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) | 449 | if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) |
418 | rt2x00crypto_tx_copy_iv(skb, iv_len); | 450 | rt2x00crypto_tx_copy_iv(skb, &txdesc); |
419 | else | 451 | else |
420 | rt2x00crypto_tx_remove_iv(skb, iv_len); | 452 | rt2x00crypto_tx_remove_iv(skb, &txdesc); |
421 | } | 453 | } |
422 | 454 | ||
455 | if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) | ||
456 | rt2x00queue_payload_align(entry->skb, true, | ||
457 | txdesc.header_length); | ||
458 | |||
423 | /* | 459 | /* |
424 | * It could be possible that the queue was corrupted and this | 460 | * It could be possible that the queue was corrupted and this |
425 | * call failed. Since we always return NETDEV_TX_OK to mac80211, | 461 | * call failed. Since we always return NETDEV_TX_OK to mac80211, |