diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00queue.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 6f78915b364c..bc1742c1d51c 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)) |
@@ -416,6 +451,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
416 | rt2x00crypto_tx_remove_iv(skb, &txdesc); | 451 | rt2x00crypto_tx_remove_iv(skb, &txdesc); |
417 | } | 452 | } |
418 | 453 | ||
454 | if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) | ||
455 | rt2x00queue_payload_align(entry->skb, true, | ||
456 | txdesc.header_length); | ||
457 | |||
419 | /* | 458 | /* |
420 | * It could be possible that the queue was corrupted and this | 459 | * It could be possible that the queue was corrupted and this |
421 | * call failed. Since we always return NETDEV_TX_OK to mac80211, | 460 | * call failed. Since we always return NETDEV_TX_OK to mac80211, |