aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c39
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
151void 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
151static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, 180static 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,