aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00queue.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/rt2x00/rt2x00queue.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00queue.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c103
1 files changed, 52 insertions, 51 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 577029efe320..a0bd36fc4d2e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -1,5 +1,6 @@
1/* 1/*
2 Copyright (C) 2004 - 2009 rt2x00 SourceForge Project 2 Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
3 Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
3 <http://rt2x00.serialmonkey.com> 4 <http://rt2x00.serialmonkey.com>
4 5
5 This program is free software; you can redistribute it and/or modify 6 This program is free software; you can redistribute it and/or modify
@@ -23,6 +24,7 @@
23 Abstract: rt2x00 queue specific routines. 24 Abstract: rt2x00 queue specific routines.
24 */ 25 */
25 26
27#include <linux/slab.h>
26#include <linux/kernel.h> 28#include <linux/kernel.h>
27#include <linux/module.h> 29#include <linux/module.h>
28#include <linux/dma-mapping.h> 30#include <linux/dma-mapping.h>
@@ -103,7 +105,7 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
103 * is also mapped to the DMA so it can be used for transfering 105 * is also mapped to the DMA so it can be used for transfering
104 * additional descriptor information to the hardware. 106 * additional descriptor information to the hardware.
105 */ 107 */
106 skb_push(skb, rt2x00dev->hw->extra_tx_headroom); 108 skb_push(skb, rt2x00dev->ops->extra_tx_headroom);
107 109
108 skbdesc->skb_dma = 110 skbdesc->skb_dma =
109 dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); 111 dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
@@ -111,7 +113,7 @@ void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
111 /* 113 /*
112 * Restore data pointer to original location again. 114 * Restore data pointer to original location again.
113 */ 115 */
114 skb_pull(skb, rt2x00dev->hw->extra_tx_headroom); 116 skb_pull(skb, rt2x00dev->ops->extra_tx_headroom);
115 117
116 skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; 118 skbdesc->flags |= SKBDESC_DMA_MAPPED_TX;
117} 119}
@@ -133,7 +135,7 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
133 * by the driver, but it was actually mapped to DMA. 135 * by the driver, but it was actually mapped to DMA.
134 */ 136 */
135 dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, 137 dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma,
136 skb->len + rt2x00dev->hw->extra_tx_headroom, 138 skb->len + rt2x00dev->ops->extra_tx_headroom,
137 DMA_TO_DEVICE); 139 DMA_TO_DEVICE);
138 skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; 140 skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX;
139 } 141 }
@@ -161,10 +163,10 @@ void rt2x00queue_align_frame(struct sk_buff *skb)
161 skb_trim(skb, frame_length); 163 skb_trim(skb, frame_length);
162} 164}
163 165
164void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_lengt) 166void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length)
165{ 167{
166 unsigned int frame_length = skb->len; 168 unsigned int frame_length = skb->len;
167 unsigned int align = ALIGN_SIZE(skb, header_lengt); 169 unsigned int align = ALIGN_SIZE(skb, header_length);
168 170
169 if (!align) 171 if (!align)
170 return; 172 return;
@@ -176,55 +178,45 @@ void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_lengt)
176 178
177void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) 179void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
178{ 180{
179 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 181 unsigned int payload_length = skb->len - header_length;
180 unsigned int frame_length = skb->len;
181 unsigned int header_align = ALIGN_SIZE(skb, 0); 182 unsigned int header_align = ALIGN_SIZE(skb, 0);
182 unsigned int payload_align = ALIGN_SIZE(skb, header_length); 183 unsigned int payload_align = ALIGN_SIZE(skb, header_length);
183 unsigned int l2pad = 4 - (payload_align - header_align); 184 unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
184 185
185 if (header_align == payload_align) { 186 /*
186 /* 187 * Adjust the header alignment if the payload needs to be moved more
187 * Both header and payload must be moved the same 188 * than the header.
188 * amount of bytes to align them properly. This means 189 */
189 * we don't use the L2 padding but just move the entire 190 if (payload_align > header_align)
190 * frame. 191 header_align += 4;
191 */
192 rt2x00queue_align_frame(skb);
193 } else if (!payload_align) {
194 /*
195 * Simple L2 padding, only the header needs to be moved,
196 * the payload is already properly aligned.
197 */
198 skb_push(skb, header_align);
199 memmove(skb->data, skb->data + header_align, frame_length);
200 skbdesc->flags |= SKBDESC_L2_PADDED;
201 } else {
202 /*
203 *
204 * Complicated L2 padding, both header and payload need
205 * to be moved. By default we only move to the start
206 * of the buffer, so our header alignment needs to be
207 * increased if there is not enough room for the header
208 * to be moved.
209 */
210 if (payload_align > header_align)
211 header_align += 4;
212 192
213 skb_push(skb, header_align); 193 /* There is nothing to do if no alignment is needed */
214 memmove(skb->data, skb->data + header_align, header_length); 194 if (!header_align)
195 return;
196
197 /* Reserve the amount of space needed in front of the frame */
198 skb_push(skb, header_align);
199
200 /*
201 * Move the header.
202 */
203 memmove(skb->data, skb->data + header_align, header_length);
204
205 /* Move the payload, if present and if required */
206 if (payload_length && payload_align)
215 memmove(skb->data + header_length + l2pad, 207 memmove(skb->data + header_length + l2pad,
216 skb->data + header_length + l2pad + header_align, 208 skb->data + header_length + l2pad + payload_align,
217 frame_length - header_length); 209 payload_length);
218 skbdesc->flags |= SKBDESC_L2_PADDED; 210
219 } 211 /* Trim the skb to the correct size */
212 skb_trim(skb, header_length + l2pad + payload_length);
220} 213}
221 214
222void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) 215void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
223{ 216{
224 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 217 unsigned int l2pad = L2PAD_SIZE(header_length);
225 unsigned int l2pad = 4 - (header_length & 3);
226 218
227 if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) 219 if (!l2pad)
228 return; 220 return;
229 221
230 memmove(skb->data + l2pad, skb->data, header_length); 222 memmove(skb->data + l2pad, skb->data, header_length);
@@ -345,7 +337,9 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
345 * Header and alignment information. 337 * Header and alignment information.
346 */ 338 */
347 txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); 339 txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
348 txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); 340 if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags) &&
341 (entry->skb->len > txdesc->header_length))
342 txdesc->l2pad = L2PAD_SIZE(txdesc->header_length);
349 343
350 /* 344 /*
351 * Check whether this frame is to be acked. 345 * Check whether this frame is to be acked.
@@ -386,10 +380,13 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
386 380
387 /* 381 /*
388 * Beacons and probe responses require the tsf timestamp 382 * Beacons and probe responses require the tsf timestamp
389 * to be inserted into the frame. 383 * to be inserted into the frame, except for a frame that has been injected
384 * through a monitor interface. This latter is needed for testing a
385 * monitor interface.
390 */ 386 */
391 if (ieee80211_is_beacon(hdr->frame_control) || 387 if ((ieee80211_is_beacon(hdr->frame_control) ||
392 ieee80211_is_probe_resp(hdr->frame_control)) 388 ieee80211_is_probe_resp(hdr->frame_control)) &&
389 (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
393 __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); 390 __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
394 391
395 /* 392 /*
@@ -453,7 +450,8 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
453 rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); 450 rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid);
454} 451}
455 452
456int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) 453int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
454 bool local)
457{ 455{
458 struct ieee80211_tx_info *tx_info; 456 struct ieee80211_tx_info *tx_info;
459 struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); 457 struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
@@ -494,10 +492,13 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
494 skbdesc->tx_rate_idx = rate_idx; 492 skbdesc->tx_rate_idx = rate_idx;
495 skbdesc->tx_rate_flags = rate_flags; 493 skbdesc->tx_rate_flags = rate_flags;
496 494
495 if (local)
496 skbdesc->flags |= SKBDESC_NOT_MAC80211;
497
497 /* 498 /*
498 * When hardware encryption is supported, and this frame 499 * When hardware encryption is supported, and this frame
499 * is to be encrypted, we should strip the IV/EIV data from 500 * is to be encrypted, we should strip the IV/EIV data from
500 * the frame so we can provide it to the driver seperately. 501 * the frame so we can provide it to the driver separately.
501 */ 502 */
502 if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && 503 if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
503 !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { 504 !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {